+++ /dev/null
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Mathias Hasselmann
- * Jan Arne Petersen
- */
-
-#include "gtktoolpaletteprivate.h"
-
-#include <gtk/gtk.h>
-#include <math.h>
-#include <string.h>
-
-#define P_(msgid) (msgid)
-
-#define ANIMATION_TIMEOUT 50
-#define ANIMATION_DURATION (ANIMATION_TIMEOUT * 4)
-#define DEFAULT_ANIMATION_STATE TRUE
-#define DEFAULT_EXPANDER_SIZE 16
-#define DEFAULT_HEADER_SPACING 2
-
-#define DEFAULT_NAME NULL
-#define DEFAULT_COLLAPSED FALSE
-#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE
-
-/**
- * SECTION:GtkToolItemGroup
- * @short_description: A sub container used in a tool palette
- * @include: gtktoolitemgroup.h
- *
- * An #GtkToolItemGroup is used together with #GtkToolPalette to add #GtkToolItem<!-- -->s to a palette like container
- * with different categories and drag and drop support.
- *
- * Since: 2.18
- */
-
-enum
-{
- PROP_NONE,
- PROP_NAME,
- PROP_COLLAPSED,
- PROP_ELLIPSIZE,
- PROP_RELIEF
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_HOMOGENEOUS,
- CHILD_PROP_EXPAND,
- CHILD_PROP_FILL,
- CHILD_PROP_NEW_ROW,
- CHILD_PROP_POSITION,
-};
-
-typedef struct _GtkToolItemGroupChild GtkToolItemGroupChild;
-
-struct _GtkToolItemGroupPrivate
-{
- GtkWidget *header;
-
- GList *children;
-
- gboolean animation;
- gint64 animation_start;
- GSource *animation_timeout;
- GtkExpanderStyle expander_style;
- gint expander_size;
- gint header_spacing;
- PangoEllipsizeMode ellipsize;
-
- gulong focus_set_id;
- GtkWidget *toplevel;
-
- GtkSettings *settings;
- gulong settings_connection;
-
- guint collapsed : 1;
-};
-
-struct _GtkToolItemGroupChild
-{
- GtkToolItem *item;
-
- guint homogeneous : 1;
- guint expand : 1;
- guint fill : 1;
- guint new_row : 1;
-};
-
-static void gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (GtkToolItemGroup, gtk_tool_item_group, GTK_TYPE_CONTAINER,
-G_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL, gtk_tool_item_group_tool_shell_init));
-
-static GtkWidget*
-gtk_tool_item_group_get_alignment (GtkToolItemGroup *group)
-{
- return gtk_bin_get_child (GTK_BIN (group->priv->header));
-}
-
-static GtkWidget*
-gtk_tool_item_group_get_label (GtkToolItemGroup *group)
-{
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- return gtk_bin_get_child (GTK_BIN (alignment));
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent));
-
- return GTK_ORIENTATION_VERTICAL;
-}
-
-static GtkToolbarStyle
-gtk_tool_item_group_get_style (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_style (GTK_TOOL_PALETTE (parent));
-
- return GTK_TOOLBAR_ICONS;
-}
-
-static GtkIconSize
-gtk_tool_item_group_get_icon_size (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_icon_size (GTK_TOOL_PALETTE (parent));
-
- return GTK_ICON_SIZE_SMALL_TOOLBAR;
-}
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
-
-static PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize_mode (GtkToolShell *shell)
-{
- return GTK_TOOL_ITEM_GROUP (shell)->priv->ellipsize;
-}
-
-static gfloat
-gtk_tool_item_group_get_text_alignment (GtkToolShell *shell)
-{
- if (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell) ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell))
- return 0.0;
-
- return 0.5;
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_text_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- {
- GtkOrientation orientation = gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent));
- if (GTK_ORIENTATION_HORIZONTAL == orientation &&
- (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell)/* ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell)*/))
- return GTK_ORIENTATION_VERTICAL;
- }
-
- return GTK_ORIENTATION_HORIZONTAL;
-}
-
-static GtkSizeGroup *
-gtk_tool_item_group_get_text_size_group (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return _gtk_tool_palette_get_size_group (GTK_TOOL_PALETTE (parent));
-
- return NULL;
-}
-
-#endif
-
-static void
-animation_change_notify (GtkToolItemGroup *group)
-{
- GtkSettings *settings = group->priv->settings;
- gboolean animation;
-
- if (settings)
- g_object_get (settings,
- "gtk-enable-animations", &animation,
- NULL);
- else
- animation = DEFAULT_ANIMATION_STATE;
-
- group->priv->animation = animation;
-}
-
-static void
-gtk_tool_item_group_settings_change_notify (GtkSettings *settings,
- const GParamSpec *pspec,
- GtkToolItemGroup *group)
-{
- if (! strcmp (pspec->name, "gtk-enable-animations"))
- {
- animation_change_notify (group);
- }
-}
-
-static void
-gtk_tool_item_group_screen_changed (GtkWidget *widget,
- GdkScreen *previous_screen)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkSettings *old_settings = priv->settings;
- GtkSettings *settings;
-
- if (gtk_widget_has_screen (GTK_WIDGET (group)))
- settings = gtk_widget_get_settings (GTK_WIDGET (group));
- else
- settings = NULL;
-
- if (settings == old_settings)
- return;
-
- if (old_settings)
- {
- g_signal_handler_disconnect (old_settings, priv->settings_connection);
- g_object_unref (old_settings);
- }
-
- if (settings)
- {
- priv->settings_connection =
- g_signal_connect (settings, "notify",
- G_CALLBACK (gtk_tool_item_group_settings_change_notify),
- group);
- priv->settings = g_object_ref (settings);
- }
- else
- priv->settings = NULL;
-
- animation_change_notify (group);
-}
-
-static void
-gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface)
-{
- iface->get_icon_size = gtk_tool_item_group_get_icon_size;
- iface->get_orientation = gtk_tool_item_group_get_orientation;
- iface->get_style = gtk_tool_item_group_get_style;
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- iface->get_text_alignment = gtk_tool_item_group_get_text_alignment;
- iface->get_text_orientation = gtk_tool_item_group_get_text_orientation;
- iface->get_text_size_group = gtk_tool_item_group_get_text_size_group;
- iface->get_ellipsize_mode = gtk_tool_item_group_get_ellipsize_mode;
-#endif
-}
-
-static gboolean
-gtk_tool_item_group_header_expose_event_cb (GtkWidget *widget,
- GdkEventExpose *event,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkExpanderStyle expander_style;
- GtkOrientation orientation;
- gint x, y;
- GtkTextDirection direction;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- expander_style = group->priv->expander_style;
- direction = gtk_widget_get_direction (widget);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- if (GTK_TEXT_DIR_RTL == direction)
- x = widget->allocation.x + widget->allocation.width - group->priv->expander_size / 2;
- else
- x = widget->allocation.x + group->priv->expander_size / 2;
- y = widget->allocation.y + widget->allocation.height / 2;
- }
- else
- {
- x = widget->allocation.x + widget->allocation.width / 2;
- y = widget->allocation.y + group->priv->expander_size / 2;
-
- /* Unfortunatly gtk_paint_expander() doesn't support rotated drawing
- * modes. Luckily the following shady arithmetics produce the desired
- * result. */
- expander_style = GTK_EXPANDER_EXPANDED - expander_style; /* XXX */
- }
-
- gtk_paint_expander (widget->style, widget->window,
- group->priv->header->state,
- &event->area, GTK_WIDGET (group),
- "tool-palette-header", x, y,
- expander_style);
-
- return FALSE;
-}
-
-static void
-gtk_tool_item_group_header_size_request_cb (GtkWidget *widget G_GNUC_UNUSED,
- GtkRequisition *requisition,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- requisition->height = MAX (requisition->height, group->priv->expander_size);
-}
-
-static void
-gtk_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkWidget *parent = gtk_widget_get_parent (data);
-
- if (group->priv->collapsed ||
- !GTK_IS_TOOL_PALETTE (parent) ||
- !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data))
- gtk_tool_item_group_set_collapsed (group, !group->priv->collapsed);
-}
-
-static void
-gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group)
-{
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment));
- GtkWidget *widget = GTK_WIDGET (group);
- gint dx = 0, dy = 0;
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- gtk_widget_style_get (widget,
- "header-spacing", &group->priv->header_spacing,
- "expander-size", &group->priv->expander_size,
- NULL);
-
- switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)))
- {
- case GTK_ORIENTATION_HORIZONTAL:
- dy = group->priv->header_spacing + group->priv->expander_size;
- gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
- if (GTK_TEXT_DIR_RTL == direction)
- gtk_label_set_angle (GTK_LABEL (label), -90);
- else
- gtk_label_set_angle (GTK_LABEL (label), 90);
- break;
-
- case GTK_ORIENTATION_VERTICAL:
- dx = group->priv->header_spacing + group->priv->expander_size;
- gtk_label_set_ellipsize (GTK_LABEL (label), group->priv->ellipsize);
- gtk_label_set_angle (GTK_LABEL (label), 0);
- break;
- }
-
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), dy, 0, dx, 0);
-}
-
-static void
-gtk_tool_item_group_init (GtkToolItemGroup *group)
-{
- GtkWidget *alignment;
- GtkWidget *label;
-
- gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE);
-
- group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
- GTK_TYPE_TOOL_ITEM_GROUP,
- GtkToolItemGroupPrivate);
-
- group->priv->children = NULL;
- group->priv->header_spacing = DEFAULT_HEADER_SPACING;
- group->priv->expander_size = DEFAULT_EXPANDER_SIZE;
- group->priv->expander_style = GTK_EXPANDER_EXPANDED;
-
- label = gtk_label_new (NULL);
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
- gtk_container_add (GTK_CONTAINER (alignment), label);
- gtk_widget_show_all (alignment);
-
- gtk_widget_push_composite_child ();
- group->priv->header = gtk_button_new ();
- gtk_widget_set_composite_name (group->priv->header, "header");
- gtk_widget_pop_composite_child ();
-
- g_object_ref_sink (group->priv->header);
- gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE);
- gtk_container_add (GTK_CONTAINER (group->priv->header), alignment);
- gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group));
-
- gtk_tool_item_group_header_adjust_style (group);
-
- g_signal_connect_after (alignment, "expose-event",
- G_CALLBACK (gtk_tool_item_group_header_expose_event_cb),
- group);
- g_signal_connect_after (alignment, "size-request",
- G_CALLBACK (gtk_tool_item_group_header_size_request_cb),
- group);
-
- g_signal_connect (group->priv->header, "clicked",
- G_CALLBACK (gtk_tool_item_group_header_clicked_cb),
- group);
-}
-
-static void
-gtk_tool_item_group_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_NAME:
- gtk_tool_item_group_set_name (group, g_value_get_string (value));
- break;
-
- case PROP_COLLAPSED:
- gtk_tool_item_group_set_collapsed (group, g_value_get_boolean (value));
- break;
-
- case PROP_ELLIPSIZE:
- gtk_tool_item_group_set_ellipsize (group, g_value_get_enum (value));
- break;
- case PROP_RELIEF:
- gtk_tool_item_group_set_header_relief (group, g_value_get_enum(value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_NAME:
- g_value_set_string (value, gtk_tool_item_group_get_name (group));
- break;
-
- case PROP_COLLAPSED:
- g_value_set_boolean (value, gtk_tool_item_group_get_collapsed (group));
- break;
-
- case PROP_ELLIPSIZE:
- g_value_set_enum (value, gtk_tool_item_group_get_ellipsize (group));
- break;
-
- case PROP_RELIEF:
- g_value_set_enum (value, gtk_tool_item_group_get_header_relief (group));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_finalize (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- if (group->priv->children)
- {
- g_list_free (group->priv->children);
- group->priv->children = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_item_group_dispose (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- if (group->priv->toplevel)
- {
- /* disconnect focus tracking handler */
- g_signal_handler_disconnect (group->priv->toplevel,
- group->priv->focus_set_id);
-
- group->priv->focus_set_id = 0;
- group->priv->toplevel = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_item_group_get_item_size (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_get_item_size (GTK_TOOL_PALETTE (parent), item_size, homogeneous_only, requested_rows);
- else
- _gtk_tool_item_group_item_size_request (group, item_size, homogeneous_only, requested_rows);
-}
-
-static void
-gtk_tool_item_group_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkOrientation orientation;
- GtkRequisition item_size;
- gint requested_rows;
-
- if (group->priv->children && gtk_tool_item_group_get_name (group))
- {
- gtk_widget_size_request (group->priv->header, requisition);
- gtk_widget_show (group->priv->header);
- }
- else
- {
- requisition->width = requisition->height = 0;
- gtk_widget_hide (group->priv->header);
- }
-
- gtk_tool_item_group_get_item_size (group, &item_size, FALSE, &requested_rows);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- requisition->width = MAX (requisition->width, item_size.width);
- else
- requisition->height = MAX (requisition->height, item_size.height * requested_rows);
-
- requisition->width += border_width * 2;
- requisition->height += border_width * 2;
-}
-
-static gboolean
-gtk_tool_item_group_is_item_visible (GtkToolItemGroup *group,
- GtkToolItemGroupChild *child)
-{
- GtkToolbarStyle style;
- GtkOrientation orientation;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* horizontal tool palettes with text style support only homogeneous items */
- if (!child->homogeneous &&
- GTK_ORIENTATION_HORIZONTAL == orientation &&
- GTK_TOOLBAR_TEXT == style)
- return FALSE;
-
- return
- (GTK_WIDGET_VISIBLE (child->item)) &&
- (GTK_ORIENTATION_VERTICAL == orientation ?
- gtk_tool_item_get_visible_vertical (child->item) :
- gtk_tool_item_get_visible_horizontal (child->item));
-}
-
-static inline unsigned
-udiv (unsigned x,
- unsigned y)
-{
- return (x + y - 1) / y;
-}
-
-static void
-gtk_tool_item_group_real_size_query (GtkWidget *widget,
- GtkAllocation *allocation,
- GtkRequisition *inquery)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- gint min_rows;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- item_size.width = MIN (item_size.width, allocation->width);
- else
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = 0;
- item_area.height = 0;
-
- /* figure out the required columns (n_columns) and rows (n_rows) to place all items */
- if (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout)
- {
- guint n_columns;
- gint n_rows;
- GList *it;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- gboolean new_row = FALSE;
- gint row = -1;
- guint col = 0;
-
- item_area.width = allocation->width - 2 * border_width;
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- /* calculate required rows for n_columns columns */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
- n_rows = row + 2;
- }
- else
- {
- guint *row_min_width;
- gint row = -1;
- gboolean new_row = TRUE;
- guint col = 0, min_col, max_col = 0, all_items = 0;
- gint i;
-
- item_area.height = allocation->height - 2 * border_width;
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- row_min_width = g_new0 (guint, n_rows);
-
- /* calculate minimal and maximal required cols and minimal required rows */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- row_min_width[row] = 1;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- all_items++;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
-
- col += width;
- all_items += width;
-
- row_min_width[row] = MAX (row_min_width[row], width);
- }
-
- max_col = MAX (max_col, col);
- }
-
- /* calculate minimal required cols */
- min_col = udiv (all_items, n_rows);
-
- for (i = 0; i <= row; i++)
- {
- min_col = MAX (min_col, row_min_width[i]);
- }
-
- /* simple linear search for minimal required columns for the given maximal number of rows (n_rows) */
- for (n_columns = min_col; n_columns < max_col; n_columns ++)
- {
- new_row = TRUE;
- row = -1;
- /* calculate required rows for n_columns columns */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
-
- if (row < n_rows)
- break;
- }
- }
-
- item_area.width = item_size.width * n_columns;
- item_area.height = item_size.height * n_rows;
- }
-
- inquery->width = 0;
- inquery->height = 0;
-
- /* figure out header widget size */
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (group->priv->header, &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- inquery->height += child_requisition.height;
- else
- inquery->width += child_requisition.width;
- }
-
- /* report effective widget size */
- inquery->width += item_area.width + 2 * border_width;
- inquery->height += item_area.height + 2 * border_width;
-}
-
-static void
-gtk_tool_item_group_real_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkRequisition child_requisition;
- GtkAllocation child_allocation;
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- GList *it;
-
- gint n_columns, n_rows = 1;
- gint min_rows;
-
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* chain up */
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation);
-
- child_allocation.x = border_width;
- child_allocation.y = border_width;
-
- /* place the header widget */
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- gtk_widget_size_request (group->priv->header, &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- child_allocation.width = allocation->width;
- child_allocation.height = child_requisition.height;
- }
- else
- {
- child_allocation.width = child_requisition.width;
- child_allocation.height = allocation->height;
-
- if (GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - border_width - child_allocation.width;
- }
-
- gtk_widget_size_allocate (group->priv->header, &child_allocation);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- child_allocation.y += child_allocation.height;
- else if (GTK_TEXT_DIR_RTL != direction)
- child_allocation.x += child_allocation.width;
- else
- child_allocation.x = border_width;
- }
- else
- child_requisition.width = child_requisition.height = 0;
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- /* figure out the available columns and size of item_area */
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- item_size.width = MIN (item_size.width, allocation->width);
-
- item_area.width = allocation->width - 2 * border_width;
- item_area.height = allocation->height - 2 * border_width - child_requisition.height;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- item_size.width = item_area.width / n_columns;
- }
- else
- {
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = allocation->width - 2 * border_width - child_requisition.width;
- item_area.height = allocation->height - 2 * border_width;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- item_size.height = item_area.height / n_rows;
- }
-
- item_area.x = child_allocation.x;
- item_area.y = child_allocation.y;
-
- /* when expanded or in transition, place the tool items in a grid like layout */
- if (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout)
- {
- gint col = 0, row = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- gint col_child;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- {
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
-
- continue;
- }
-
- /* for non homogeneous widgets request the required size */
- child_requisition.width = 0;
-
- if (!child->homogeneous)
- {
- gtk_widget_size_request (GTK_WIDGET (child->item), &child_requisition);
- child_requisition.width = MIN (child_requisition.width, item_area.width);
- }
-
- /* select next row if at end of row */
- if (col > 0 && (child->new_row || (col * item_size.width) + MAX (child_requisition.width, item_size.width) > item_area.width))
- {
- row++;
- col = 0;
- child_allocation.y += child_allocation.height;
- }
-
- col_child = col;
-
- /* calculate the position and size of the item */
- if (!child->homogeneous)
- {
- gint col_width;
- gint width;
-
- if (!child->expand)
- col_width = udiv (child_requisition.width, item_size.width);
- else
- col_width = n_columns - col;
-
- width = col_width * item_size.width;
-
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - col_width);
-
- if (child->fill)
- {
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = width;
- }
- else
- {
- child_allocation.x =
- (item_area.x + col_child * item_size.width +
- (width - child_requisition.width) / 2);
- child_allocation.width = child_requisition.width;
- }
-
- col += col_width;
- }
- else
- {
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - 1);
-
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = item_size.width;
-
- col++;
- }
-
- child_allocation.height = item_size.height;
-
- gtk_widget_size_allocate (GTK_WIDGET (child->item), &child_allocation);
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), TRUE);
- }
-
- child_allocation.y += item_size.height;
- }
-
- /* or just hide all items, when collapsed */
-
- else
- {
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
- }
- }
-}
-
-static void
-gtk_tool_item_group_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- gtk_tool_item_group_real_size_allocate (widget, allocation);
-
- if (GTK_WIDGET_MAPPED (widget))
- gdk_window_invalidate_rect (widget->window, NULL, FALSE);
-}
-
-static void
-gtk_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED,
- GtkWidget *widget,
- gpointer user_data)
-{
- GtkAdjustment *adjustment;
- GtkWidget *p;
-
- /* Find this group's parent widget in the focused widget's anchestry. */
- for (p = widget; p; p = gtk_widget_get_parent (p))
- if (p == user_data)
- {
- p = gtk_widget_get_parent (p);
- break;
- }
-
- if (GTK_IS_TOOL_PALETTE (p))
- {
- /* Check that the focused widgets is fully visible within
- * the group's parent widget and make it visible otherwise. */
-
- adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p));
- adjustment = gtk_tool_palette_get_vadjustment (GTK_TOOL_PALETTE (p));
-
- if (adjustment)
- {
- int y;
-
- /* Handle vertical adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, NULL, &y) && y < 0)
- {
- y += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height);
- }
- else if (gtk_widget_translate_coordinates
- (widget, p, 0, widget->allocation.height, NULL, &y) &&
- y > p->allocation.height)
- {
- y += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y);
- }
- }
-
- adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p));
-
- if (adjustment)
- {
- int x;
-
- /* Handle horizontal adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, &x, NULL) && x < 0)
- {
- x += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width);
- }
- else if (gtk_widget_translate_coordinates
- (widget, p, widget->allocation.width, 0, &x, NULL) &&
- x > p->allocation.width)
- {
- x += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x);
- }
-
- return;
- }
- }
-}
-
-static void
-gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group,
- GtkWidget *toplevel)
-{
- if (toplevel != group->priv->toplevel)
- {
- if (group->priv->toplevel)
- {
- /* Disconnect focus tracking handler. */
- g_signal_handler_disconnect (group->priv->toplevel,
- group->priv->focus_set_id);
-
- group->priv->focus_set_id = 0;
- group->priv->toplevel = NULL;
- }
-
- if (toplevel)
- {
- /* Install focus tracking handler. We connect to the window's
- * set-focus signal instead of connecting to the focus signal of
- * each child to:
- *
- * 1) Reduce the number of signal handlers used.
- * 2) Avoid special handling for group headers.
- * 3) Catch focus grabs not only for direct children,
- * but also for nested widgets.
- */
- group->priv->focus_set_id =
- g_signal_connect (toplevel, "set-focus",
- G_CALLBACK (gtk_tool_item_group_set_focus_cb),
- group);
-
- group->priv->toplevel = toplevel;
- }
- }
-}
-
-static void
-gtk_tool_item_group_realize (GtkWidget *widget)
-{
- GtkWidget *toplevel_window;
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- GdkWindowAttr attributes;
- GdkDisplay *display;
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - border_width * 2;
- attributes.height = widget->allocation.height - border_width * 2;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
-
- display = gdk_drawable_get_display (widget->window);
-
- if (gdk_display_supports_composite (display))
- gdk_window_set_composited (widget->window, TRUE);
-
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_set_parent_window,
- widget->window);
-
- gtk_widget_queue_resize_no_redraw (widget);
-
- toplevel_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget),
- toplevel_window);
-}
-
-static void
-gtk_tool_item_group_unrealize (GtkWidget *widget)
-{
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget), NULL);
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->unrealize (widget);
-}
-
-static void
-gtk_tool_item_group_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
-{
- gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget));
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_set (widget, previous_style);
-}
-
-static void
-gtk_tool_item_group_add (GtkContainer *container,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM (widget));
-
- gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (container),
- GTK_TOOL_ITEM (widget), -1);
-}
-
-static void
-gtk_tool_item_group_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolItemGroup *group;
- GList *it;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- group = GTK_TOOL_ITEM_GROUP (container);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child_info = it->data;
-
- if ((GtkWidget *)child_info->item == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- g_free (child_info);
- group->priv->children = g_list_delete_link (group->priv->children, it);
-
- gtk_widget_queue_resize (GTK_WIDGET (container));
- break;
- }
- }
-}
-
-static void
-gtk_tool_item_group_forall (GtkContainer *container,
- gboolean internals,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GList *children;
-
- if (internals && group->priv->header)
- callback (group->priv->header, callback_data);
-
- children = group->priv->children;
- while (children)
- {
- GtkToolItemGroupChild *child = children->data;
- children = children->next; /* store pointer before call to callback
- because the child pointer is invalid if the
- child->item is removed from the item group
- in callback */
-
- callback (GTK_WIDGET (child->item), callback_data);
- }
-}
-
-static GType
-gtk_tool_item_group_child_type (GtkContainer *container G_GNUC_UNUSED)
-{
- return GTK_TYPE_TOOL_ITEM;
-}
-
-static GtkToolItemGroupChild *
-gtk_tool_item_group_get_child (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint *position,
- GList **link)
-{
- guint i;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), NULL);
-
- for (it = group->priv->children, i = 0; it != NULL; it = it->next, ++i)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (child->item == item)
- {
- if (position)
- *position = i;
-
- if (link)
- *link = it;
-
- return child;
- }
- }
-
- return NULL;
-}
-
-static void
-gtk_tool_item_group_get_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean *homogeneous,
- gboolean *expand,
- gboolean *fill,
- gboolean *new_row)
-{
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- if (expand)
- *expand = child->expand;
-
- if (homogeneous)
- *homogeneous = child->homogeneous;
-
- if (fill)
- *fill = child->fill;
-
- if (new_row)
- *new_row = child->new_row;
-}
-
-static void
-gtk_tool_item_group_set_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean homogeneous,
- gboolean expand,
- gboolean fill,
- gboolean new_row)
-{
- GtkToolItemGroupChild *child;
- gboolean changed = FALSE;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- gtk_widget_freeze_child_notify (GTK_WIDGET (item));
-
- if (child->homogeneous != homogeneous)
- {
- child->homogeneous = homogeneous;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "homogeneous");
- }
- if (child->expand != expand)
- {
- child->expand = expand;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "expand");
- }
- if (child->fill != fill)
- {
- child->fill = fill;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "fill");
- }
- if (child->new_row != new_row)
- {
- child->new_row = new_row;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "new-row");
- }
-
- gtk_widget_thaw_child_notify (GTK_WIDGET (item));
-
- if (changed && GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-static void
-gtk_tool_item_group_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- gtk_tool_item_group_set_item_packing (group, item,
- g_value_get_boolean (value),
- expand,
- fill,
- new_row);
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- g_value_get_boolean (value),
- fill,
- new_row);
- break;
-
- case CHILD_PROP_FILL:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- g_value_get_boolean (value),
- new_row);
- break;
-
- case CHILD_PROP_NEW_ROW:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- fill,
- g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_POSITION:
- gtk_tool_item_group_set_item_position (group, item, g_value_get_int (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- g_value_set_boolean (value, homogeneous);
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, expand);
- break;
-
- case CHILD_PROP_FILL:
- g_value_set_boolean (value, fill);
- break;
-
- case CHILD_PROP_NEW_ROW:
- g_value_set_boolean (value, new_row);
- break;
-
- case CHILD_PROP_POSITION:
- g_value_set_int (value, gtk_tool_item_group_get_item_position (group, item));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_class_init (GtkToolItemGroupClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_item_group_set_property;
- oclass->get_property = gtk_tool_item_group_get_property;
- oclass->finalize = gtk_tool_item_group_finalize;
- oclass->dispose = gtk_tool_item_group_dispose;
-
- wclass->size_request = gtk_tool_item_group_size_request;
- wclass->size_allocate = gtk_tool_item_group_size_allocate;
- wclass->realize = gtk_tool_item_group_realize;
- wclass->unrealize = gtk_tool_item_group_unrealize;
- wclass->style_set = gtk_tool_item_group_style_set;
- wclass->screen_changed = gtk_tool_item_group_screen_changed;
-
- cclass->add = gtk_tool_item_group_add;
- cclass->remove = gtk_tool_item_group_remove;
- cclass->forall = gtk_tool_item_group_forall;
- cclass->child_type = gtk_tool_item_group_child_type;
- cclass->set_child_property = gtk_tool_item_group_set_child_property;
- cclass->get_child_property = gtk_tool_item_group_get_child_property;
-
- g_object_class_install_property (oclass, PROP_NAME,
- g_param_spec_string ("name",
- P_("Name"),
- P_("The name of this item group"),
- DEFAULT_NAME,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_COLLAPSED,
- g_param_spec_boolean ("collapsed",
- P_("Collapsed"),
- P_("Wether the group has been collapsed and items are hidden"),
- DEFAULT_COLLAPSED,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("ellipsize",
- P_("ellipsize"),
- P_("Ellipsize for item group headers"),
- PANGO_TYPE_ELLIPSIZE_MODE, DEFAULT_ELLIPSIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("header-relief",
- P_("header-relif"),
- P_("Relief of the group header button"),
- GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_widget_class_install_style_property (wclass,
- g_param_spec_int ("expander-size",
- P_("Expander Size"),
- P_("Size of the expander arrow"),
- 0,
- G_MAXINT,
- DEFAULT_EXPANDER_SIZE,
- G_PARAM_READABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_widget_class_install_style_property (wclass,
- g_param_spec_int ("header-spacing",
- P_("Header Spacing"),
- P_("Spacing between expander arrow and caption"),
- 0,
- G_MAXINT,
- DEFAULT_HEADER_SPACING,
- G_PARAM_READABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_HOMOGENEOUS,
- g_param_spec_boolean ("homogeneous",
- P_("Homogeneous"),
- P_("Whether the item should be the same size as other homogeneous items"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item should receive extra space when the toolbar grows"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL,
- g_param_spec_boolean ("fill",
- P_("Fill"),
- P_("Whether the item should fill the avaiable space"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_NEW_ROW,
- g_param_spec_boolean ("new-row",
- P_("New Row"),
- P_("Whether the item should start a new row"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_POSITION,
- g_param_spec_int ("position",
- P_("Position"),
- P_("Position of the item within this group"),
- 0,
- G_MAXINT,
- 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_type_class_add_private (cls, sizeof (GtkToolItemGroupPrivate));
-}
-
-/**
- * gtk_tool_item_group_new:
- * @name: the name of the new group.
- *
- * Creates a new tool item group with name @name.
- *
- * Returns: a new #GtkToolItemGroup.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_item_group_new (const gchar *name)
-{
- return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "name", name, NULL);
-}
-
-/**
- * gtk_tool_item_group_set_name:
- * @group: an #GtkToolItemGroup.
- * @name: the new name of of the group.
- *
- * Sets the name of the tool item group. The name is displayed in the header
- * of the group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_name (GtkToolItemGroup *group,
- const gchar *name)
-{
- const gchar *current_name;
- GtkWidget *label;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- current_name = gtk_tool_item_group_get_name (group);
-
- if (current_name != name && (!current_name || !name || strcmp (current_name, name)))
- {
- label = gtk_tool_item_group_get_label (group);
- gtk_label_set_text (GTK_LABEL (label), name);
-
- if (name && group->priv->children)
- gtk_widget_show (group->priv->header);
- else
- gtk_widget_hide (group->priv->header);
-
- g_object_notify (G_OBJECT (group), "name");
- }
-}
-
-/**
- * gtk_tool_item_group_header_relief:
- * @group: an #GtkToolItemGroup.
- * @style: The GtkReliefStyle
- *
- * Set the button relief of the group header. See #gtk_button_set_relief for
- * details
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group,
- GtkReliefStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- gtk_button_set_relief (GTK_BUTTON(group->priv->header), style);
-}
-
-static gint64
-gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group)
-{
- GTimeVal now;
- g_source_get_current_time (group->priv->animation_timeout, &now);
- return (now.tv_sec * G_USEC_PER_SEC + now.tv_usec - group->priv->animation_start) / 1000;
-}
-
-static void
-gtk_tool_item_group_force_expose (GtkToolItemGroup *group)
-{
- if (GTK_WIDGET_REALIZED (group->priv->header))
- {
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- GdkRectangle area;
-
- /* Find the header button's arrow area... */
- area.x = alignment->allocation.x;
- area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2;
- area.height = group->priv->expander_size;
- area.width = group->priv->expander_size;
-
- /* ... and invalidated it to get it animated. */
- gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE);
- }
-
- if (GTK_WIDGET_REALIZED (group))
- {
- GtkWidget *widget = GTK_WIDGET (group);
- GtkWidget *parent = gtk_widget_get_parent (widget);
- int x, y, width, height;
-
- /* Find the tool item area button's arrow area... */
- width = widget->allocation.width;
- height = widget->allocation.height;
-
- gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
-
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- height -= group->priv->header->allocation.height;
- y += group->priv->header->allocation.height;
- }
-
- /* ... and invalidated it to get it animated. */
- gtk_widget_queue_draw_area (parent, x, y, width, height);
- }
-}
-
-static gboolean
-gtk_tool_item_group_animation_cb (gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- /* Enque this early to reduce number of expose events. */
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group));
-
- /* Figure out current style of the expander arrow. */
- if (group->priv->collapsed)
- {
- if (group->priv->expander_style == GTK_EXPANDER_EXPANDED)
- group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
- else
- group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
- }
- else
- {
- if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED)
- group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
- else
- group->priv->expander_style = GTK_EXPANDER_EXPANDED;
- }
-
- gtk_tool_item_group_force_expose (group);
-
- /* Finish animation when done. */
- if (timestamp >= ANIMATION_DURATION)
- group->priv->animation_timeout = NULL;
-
- /* Ensure that all composited windows and child windows are repainted, before
- * the parent widget gets its expose-event. This is needed to avoid heavy
- * rendering artifacts. GTK+ should take care about this issue by itself I
- * guess, but currently it doesn't. Also I don't understand the parameters
- * of this issue well enough yet, to file a bug report.
- */
- gdk_window_process_updates (GTK_WIDGET (group)->window, TRUE);
-
- return (group->priv->animation_timeout != NULL);
-}
-
-/**
- * gtk_tool_item_group_set_collapsed:
- * @group: an #GtkToolItemGroup.
- * @collapsed: whether the @group should be collapsed or expanded.
- *
- * Sets whether the @group should be collapsed or expanded.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group,
- gboolean collapsed)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- GtkWidget *parent;
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
- if (GTK_IS_TOOL_PALETTE (parent) && !collapsed)
- _gtk_tool_palette_set_expanding_child (GTK_TOOL_PALETTE (parent),
- GTK_WIDGET (group));
- if (collapsed != group->priv->collapsed)
- {
- if (group->priv->animation)
- {
- GTimeVal now;
-
- g_get_current_time (&now);
-
- if (group->priv->animation_timeout)
- g_source_destroy (group->priv->animation_timeout);
-
- group->priv->animation_start = (now.tv_sec * G_USEC_PER_SEC + now.tv_usec);
- group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT);
-
- g_source_set_callback (group->priv->animation_timeout,
- gtk_tool_item_group_animation_cb,
- group, NULL);
-
- g_source_attach (group->priv->animation_timeout, NULL);
- }
- else
- {
- group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
- gtk_tool_item_group_force_expose (group);
- }
- group->priv->collapsed = collapsed;
- g_object_notify (G_OBJECT (group), "collapsed");
- }
-}
-
-/**
- * gtk_tool_item_group_set_ellipsize:
- * @group: an #GtkToolItemGroup.
- * @ellipsize: the #PangoEllipsizeMode labels in @group should use.
- *
- * Sets the ellipsization mode which should be used by labels in @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group,
- PangoEllipsizeMode ellipsize)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- if (ellipsize != group->priv->ellipsize)
- {
- group->priv->ellipsize = ellipsize;
- gtk_tool_item_group_header_adjust_style (group);
- g_object_notify (G_OBJECT (group), "ellipsize");
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- _gtk_tool_item_group_palette_reconfigured (group);
-#endif
- }
-}
-
-/**
- * gtk_tool_item_group_get_name:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the name of @group.
- *
- * Returns: the name of @group. The name is an internal string of @group and must not be modified.
- *
- * Since: 2.18
- */
-G_CONST_RETURN gchar*
-gtk_tool_item_group_get_name (GtkToolItemGroup *group)
-{
- GtkWidget *label;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_NAME);
-
- label = gtk_tool_item_group_get_label (group);
- return gtk_label_get_text (GTK_LABEL (label));
-}
-
-/**
- * gtk_tool_item_group_get_collapsed:
- * @group: an GtkToolItemGroup.
- *
- * Gets whether @group is collapsed or expanded.
- *
- * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_COLLAPSED);
- return group->priv->collapsed;
-}
-
-/**
- * gtk_tool_item_group_get_ellipsize:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the ellipsization mode of @group.
- *
- * Returns: the #PangoEllipsizeMode of @group.
- *
- * Since: 2.18
- */
-PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_ELLIPSIZE);
- return group->priv->ellipsize;
-}
-
-/**
- * gtk_tool_item_group_get_header_relief:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the relief mode of the header button of @group.
- *
- * Returns: the #GtkReliefStyle
- *
- * Since: 2.18
- */
-GtkReliefStyle
-gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), GTK_RELIEF_NORMAL);
- return gtk_button_get_relief (GTK_BUTTON (group->priv->header));
-}
-
-/**
- * gtk_tool_item_group_insert:
- * @group: an #GtkToolItemGroup.
- * @item: the #GtkToolItem to insert into @group.
- * @position: the position of @item in @group, starting with 0. The position -1 means end of list.
- *
- * Inserts @item at @position in the list of children of @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_insert (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- GtkWidget *parent, *child_widget;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
- g_return_if_fail (position >= -1);
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- child = g_new (GtkToolItemGroupChild, 1);
- child->item = g_object_ref_sink (item);
- child->homogeneous = TRUE;
- child->expand = FALSE;
- child->fill = TRUE;
- child->new_row = FALSE;
-
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_child_set_drag_source (GTK_WIDGET (item), parent);
-
- child_widget = gtk_bin_get_child (GTK_BIN (item));
-
- if (GTK_IS_BUTTON (child_widget))
- gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), TRUE);
-
- gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_set_item_position:
- * @group: an #GtkToolItemGroup.
- * @item: the #GtkToolItem to move to a new position, should be a child of @group.
- * @position: the new position of @item in @group, starting with 0. The position -1 means end of list.
- *
- * Sets the position of @item in the list of children of @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_item_position (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- gint old_position;
- GList *link;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- g_return_if_fail (position >= -1);
-
- child = gtk_tool_item_group_get_child (group, item, &old_position, &link);
-
- g_return_if_fail (child != NULL);
-
- if (position == old_position)
- return;
-
- group->priv->children = g_list_delete_link (group->priv->children, link);
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- gtk_widget_child_notify (GTK_WIDGET (item), "position");
- if (GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_get_item_position:
- * @group: an #GtkToolItemGroup.
- * @item: a #GtkToolItem.
- *
- * Gets the position of @item in @group as index.
- *
- * Returns: the index of @item in @group or -1 if @item is no child of @group.
- *
- * Since: 2.18
- */
-gint
-gtk_tool_item_group_get_item_position (GtkToolItemGroup *group,
- GtkToolItem *item)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
-
- if (gtk_tool_item_group_get_child (group, item, &position, NULL))
- return position;
-
- return -1;
-}
-
-/**
- * gtk_tool_item_group_get_n_items:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the number of tool items in group.
- *
- * Returns: the number of tool items in group.
- *
- * Since: 2.18
- */
-guint
-gtk_tool_item_group_get_n_items (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), 0);
-
- return g_list_length (group->priv->children);
-}
-
-/**
- * gtk_tool_item_group_get_nth_item:
- * @group: an #GtkToolItemGroup.
- * @index: the index.
- *
- * Gets the tool item at index in group.
- *
- * Returns: the #GtkToolItem at index.
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group,
- guint index)
-{
- GtkToolItemGroupChild *child;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- child = g_list_nth_data (group->priv->children, index);
-
- return child != NULL ? child->item : NULL;
-}
-
-/**
- * gtk_tool_item_group_get_drop_item:
- * @group: an #GtkToolItemGroup.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the tool item at position (x, y).
- *
- * Returns: the #GtkToolItem at position (x, y).
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group,
- gint x,
- gint y)
-{
- GtkAllocation *allocation;
- GtkOrientation orientation;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- allocation = >K_WIDGET (group)->allocation;
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation->height, NULL);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- GtkToolItem *item = child->item;
- gint x0, y0;
-
- if (!item || !gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- allocation = >K_WIDGET (item)->allocation;
-
- x0 = x - allocation->x;
- y0 = y - allocation->y;
-
- if (x0 >= 0 && x0 < allocation->width &&
- y0 >= 0 && y0 < allocation->height)
- return item;
- }
-
- return NULL;
-}
-
-void
-_gtk_tool_item_group_item_size_request (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition child_requisition;
- GList *it;
- gint rows = 0;
- gboolean new_row = TRUE;
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (NULL != item_size);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- item_size->width = item_size->height = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (child->new_row || new_row)
- {
- rows++;
- new_row = FALSE;
- }
-
- if (!child->homogeneous && child->expand)
- new_row = TRUE;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &child_requisition);
-
- if (!homogeneous_only || child->homogeneous)
- item_size->width = MAX (item_size->width, child_requisition.width);
- item_size->height = MAX (item_size->height, child_requisition.height);
- }
-
- if (requested_rows)
- *requested_rows = rows;
-}
-
-void
-_gtk_tool_item_group_paint (GtkToolItemGroup *group,
- cairo_t *cr)
-{
- GtkWidget *widget = GTK_WIDGET (group);
-
- gdk_cairo_set_source_pixmap (cr, widget->window,
- widget->allocation.x,
- widget->allocation.y);
-
- if (group->priv->animation_timeout)
- {
- GtkOrientation orientation = gtk_tool_item_group_get_orientation (GTK_TOOL_SHELL (group));
- cairo_pattern_t *mask;
- gdouble v0, v1;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- v1 = widget->allocation.height;
- else
- v1 = widget->allocation.width;
-
- v0 = v1 - 256;
-
- if (!GTK_WIDGET_VISIBLE (group->priv->header))
- v0 = MAX (v0, 0);
- else if (GTK_ORIENTATION_VERTICAL == orientation)
- v0 = MAX (v0, group->priv->header->allocation.height);
- else
- v0 = MAX (v0, group->priv->header->allocation.width);
-
- v1 = MIN (v0 + 256, v1);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- v0 += widget->allocation.y;
- v1 += widget->allocation.y;
-
- mask = cairo_pattern_create_linear (0.0, v0, 0.0, v1);
- }
- else
- {
- v0 += widget->allocation.x;
- v1 += widget->allocation.x;
-
- mask = cairo_pattern_create_linear (v0, 0.0, v1, 0.0);
- }
-
- cairo_pattern_add_color_stop_rgba (mask, 0.00, 0.0, 0.0, 0.0, 1.00);
- cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.25);
- cairo_pattern_add_color_stop_rgba (mask, 0.50, 0.0, 0.0, 0.0, 0.10);
- cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.01);
- cairo_pattern_add_color_stop_rgba (mask, 1.00, 0.0, 0.0, 0.0, 0.00);
-
- cairo_mask (cr, mask);
- cairo_pattern_destroy (mask);
- }
- else
- cairo_paint (cr);
-}
-
-gint
-_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group,
- gint limit,
- gboolean vertical,
- gboolean animation)
-{
- GtkRequisition requisition;
-
- gtk_widget_size_request (GTK_WIDGET (group), &requisition);
-
- if (!group->priv->collapsed || group->priv->animation_timeout)
- {
- GtkAllocation allocation = { 0, 0, requisition.width, requisition.height };
- GtkRequisition inquery;
-
- if (vertical)
- allocation.width = limit;
- else
- allocation.height = limit;
-
- gtk_tool_item_group_real_size_query (GTK_WIDGET (group),
- &allocation, &inquery);
-
- if (vertical)
- inquery.height -= requisition.height;
- else
- inquery.width -= requisition.width;
-
- if (group->priv->animation_timeout && animation)
- {
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- timestamp = MIN (timestamp, ANIMATION_DURATION);
-
- if (group->priv->collapsed)
- timestamp = ANIMATION_DURATION - timestamp;
-
- if (vertical)
- {
- inquery.height *= timestamp;
- inquery.height /= ANIMATION_DURATION;
- }
- else
- {
- inquery.width *= timestamp;
- inquery.width /= ANIMATION_DURATION;
- }
- }
-
- if (vertical)
- requisition.height += inquery.height;
- else
- requisition.width += inquery.width;
- }
-
- return (vertical ? requisition.height : requisition.width);
-}
-
-gint
-_gtk_tool_item_group_get_height_for_width (GtkToolItemGroup *group,
- gint width)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, width, TRUE, group->priv->animation);
-}
-
-gint
-_gtk_tool_item_group_get_width_for_height (GtkToolItemGroup *group,
- gint height)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, height, FALSE, TRUE);
-}
-
-static void
-gtk_tool_palette_reconfigured_foreach_item (GtkWidget *child,
- gpointer data G_GNUC_UNUSED)
-{
- if (GTK_IS_TOOL_ITEM (child))
- gtk_tool_item_toolbar_reconfigured (GTK_TOOL_ITEM (child));
-}
-
-
-void
-_gtk_tool_item_group_palette_reconfigured (GtkToolItemGroup *group)
-{
- gtk_container_foreach (GTK_CONTAINER (group),
- gtk_tool_palette_reconfigured_foreach_item,
- NULL);
-
- gtk_tool_item_group_header_adjust_style (group);
-}
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Mathias Hasselmann
- * Jan Arne Petersen
- */
-
-#include "gtktoolpaletteprivate.h"
-
-#include <gtk/gtk.h>
-#include <math.h>
-#include <string.h>
-
-#define P_(msgid) (msgid)
-
-#define ANIMATION_TIMEOUT 50
-#define ANIMATION_DURATION (ANIMATION_TIMEOUT * 4)
-#define DEFAULT_ANIMATION_STATE TRUE
-#define DEFAULT_EXPANDER_SIZE 16
-#define DEFAULT_HEADER_SPACING 2
-
-#define DEFAULT_NAME NULL
-#define DEFAULT_COLLAPSED FALSE
-#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE
-
-/**
- * SECTION:GtkToolItemGroup
- * @short_description: A sub container used in a tool palette
- * @include: gtktoolitemgroup.h
- *
- * An #GtkToolItemGroup is used together with #GtkToolPalette to add #GtkToolItem<!-- -->s to a palette like container
- * with different categories and drag and drop support.
- *
- * Since: 2.18
- */
-
-enum
-{
- PROP_NONE,
- PROP_NAME,
- PROP_COLLAPSED,
- PROP_ELLIPSIZE,
- PROP_RELIEF
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_HOMOGENEOUS,
- CHILD_PROP_EXPAND,
- CHILD_PROP_FILL,
- CHILD_PROP_NEW_ROW,
- CHILD_PROP_POSITION,
-};
-
-typedef struct _GtkToolItemGroupChild GtkToolItemGroupChild;
-
-struct _GtkToolItemGroupPrivate
-{
- GtkWidget *header;
-
- GList *children;
-
- gboolean animation;
- gint64 animation_start;
- GSource *animation_timeout;
- GtkExpanderStyle expander_style;
- gint expander_size;
- gint header_spacing;
- PangoEllipsizeMode ellipsize;
-
- gulong focus_set_id;
- GtkWidget *toplevel;
-
- GtkSettings *settings;
- gulong settings_connection;
-
- guint collapsed : 1;
-};
-
-struct _GtkToolItemGroupChild
-{
- GtkToolItem *item;
-
- guint homogeneous : 1;
- guint expand : 1;
- guint fill : 1;
- guint new_row : 1;
-};
-
-static void gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (GtkToolItemGroup, gtk_tool_item_group, GTK_TYPE_CONTAINER,
-G_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL, gtk_tool_item_group_tool_shell_init));
-
-static GtkWidget*
-gtk_tool_item_group_get_alignment (GtkToolItemGroup *group)
-{
- return gtk_bin_get_child (GTK_BIN (group->priv->header));
-}
-
-static GtkWidget*
-gtk_tool_item_group_get_label (GtkToolItemGroup *group)
-{
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- return gtk_bin_get_child (GTK_BIN (alignment));
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent));
-
- return GTK_ORIENTATION_VERTICAL;
-}
-
-static GtkToolbarStyle
-gtk_tool_item_group_get_style (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_style (GTK_TOOL_PALETTE (parent));
-
- return GTK_TOOLBAR_ICONS;
-}
-
-static GtkIconSize
-gtk_tool_item_group_get_icon_size (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_icon_size (GTK_TOOL_PALETTE (parent));
-
- return GTK_ICON_SIZE_SMALL_TOOLBAR;
-}
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
-
-static PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize_mode (GtkToolShell *shell)
-{
- return GTK_TOOL_ITEM_GROUP (shell)->priv->ellipsize;
-}
-
-static gfloat
-gtk_tool_item_group_get_text_alignment (GtkToolShell *shell)
-{
- if (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell) ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell))
- return 0.0;
-
- return 0.5;
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_text_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- {
- GtkOrientation orientation = gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent));
- if (GTK_ORIENTATION_HORIZONTAL == orientation &&
- (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell)/* ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell)*/))
- return GTK_ORIENTATION_VERTICAL;
- }
-
- return GTK_ORIENTATION_HORIZONTAL;
-}
-
-static GtkSizeGroup *
-gtk_tool_item_group_get_text_size_group (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return _gtk_tool_palette_get_size_group (GTK_TOOL_PALETTE (parent));
-
- return NULL;
-}
-
-#endif
-
-static void
-animation_change_notify (GtkToolItemGroup *group)
-{
- GtkSettings *settings = group->priv->settings;
- gboolean animation;
-
- if (settings)
- g_object_get (settings,
- "gtk-enable-animations", &animation,
- NULL);
- else
- animation = DEFAULT_ANIMATION_STATE;
-
- group->priv->animation = animation;
-}
-
-static void
-gtk_tool_item_group_settings_change_notify (GtkSettings *settings,
- const GParamSpec *pspec,
- GtkToolItemGroup *group)
-{
- if (! strcmp (pspec->name, "gtk-enable-animations"))
- {
- animation_change_notify (group);
- }
-}
-
-static void
-gtk_tool_item_group_screen_changed (GtkWidget *widget,
- GdkScreen *previous_screen)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkSettings *old_settings = priv->settings;
- GtkSettings *settings;
-
- if (gtk_widget_has_screen (GTK_WIDGET (group)))
- settings = gtk_widget_get_settings (GTK_WIDGET (group));
- else
- settings = NULL;
-
- if (settings == old_settings)
- return;
-
- if (old_settings)
- {
- g_signal_handler_disconnect (old_settings, priv->settings_connection);
- g_object_unref (old_settings);
- }
-
- if (settings)
- {
- priv->settings_connection =
- g_signal_connect (settings, "notify",
- G_CALLBACK (gtk_tool_item_group_settings_change_notify),
- group);
- priv->settings = g_object_ref (settings);
- }
- else
- priv->settings = NULL;
-
- animation_change_notify (group);
-}
-
-static void
-gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface)
-{
- iface->get_icon_size = gtk_tool_item_group_get_icon_size;
- iface->get_orientation = gtk_tool_item_group_get_orientation;
- iface->get_style = gtk_tool_item_group_get_style;
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- iface->get_text_alignment = gtk_tool_item_group_get_text_alignment;
- iface->get_text_orientation = gtk_tool_item_group_get_text_orientation;
- iface->get_text_size_group = gtk_tool_item_group_get_text_size_group;
- iface->get_ellipsize_mode = gtk_tool_item_group_get_ellipsize_mode;
-#endif
-}
-
-static gboolean
-gtk_tool_item_group_header_expose_event_cb (GtkWidget *widget,
- GdkEventExpose *event,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkExpanderStyle expander_style;
- GtkOrientation orientation;
- gint x, y;
- GtkTextDirection direction;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- expander_style = group->priv->expander_style;
- direction = gtk_widget_get_direction (widget);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- if (GTK_TEXT_DIR_RTL == direction)
- x = widget->allocation.x + widget->allocation.width - group->priv->expander_size / 2;
- else
- x = widget->allocation.x + group->priv->expander_size / 2;
- y = widget->allocation.y + widget->allocation.height / 2;
- }
- else
- {
- x = widget->allocation.x + widget->allocation.width / 2;
- y = widget->allocation.y + group->priv->expander_size / 2;
-
- /* Unfortunatly gtk_paint_expander() doesn't support rotated drawing
- * modes. Luckily the following shady arithmetics produce the desired
- * result. */
- expander_style = GTK_EXPANDER_EXPANDED - expander_style; /* XXX */
- }
-
- gtk_paint_expander (widget->style, widget->window,
- group->priv->header->state,
- &event->area, GTK_WIDGET (group),
- "tool-palette-header", x, y,
- expander_style);
-
- return FALSE;
-}
-
-static void
-gtk_tool_item_group_header_size_request_cb (GtkWidget *widget G_GNUC_UNUSED,
- GtkRequisition *requisition,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- requisition->height = MAX (requisition->height, group->priv->expander_size);
-}
-
-static void
-gtk_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkWidget *parent = gtk_widget_get_parent (data);
-
- if (group->priv->collapsed ||
- !GTK_IS_TOOL_PALETTE (parent) ||
- !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data))
- gtk_tool_item_group_set_collapsed (group, !group->priv->collapsed);
-}
-
-static void
-gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group)
-{
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment));
- GtkWidget *widget = GTK_WIDGET (group);
- gint dx = 0, dy = 0;
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- gtk_widget_style_get (widget,
- "header-spacing", &group->priv->header_spacing,
- "expander-size", &group->priv->expander_size,
- NULL);
-
- switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)))
- {
- case GTK_ORIENTATION_HORIZONTAL:
- dy = group->priv->header_spacing + group->priv->expander_size;
- gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
- if (GTK_TEXT_DIR_RTL == direction)
- gtk_label_set_angle (GTK_LABEL (label), -90);
- else
- gtk_label_set_angle (GTK_LABEL (label), 90);
- break;
-
- case GTK_ORIENTATION_VERTICAL:
- dx = group->priv->header_spacing + group->priv->expander_size;
- gtk_label_set_ellipsize (GTK_LABEL (label), group->priv->ellipsize);
- gtk_label_set_angle (GTK_LABEL (label), 0);
- break;
- }
-
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), dy, 0, dx, 0);
-}
-
-static void
-gtk_tool_item_group_init (GtkToolItemGroup *group)
-{
- GtkWidget *alignment;
- GtkWidget *label;
-
- gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE);
-
- group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
- GTK_TYPE_TOOL_ITEM_GROUP,
- GtkToolItemGroupPrivate);
-
- group->priv->children = NULL;
- group->priv->header_spacing = DEFAULT_HEADER_SPACING;
- group->priv->expander_size = DEFAULT_EXPANDER_SIZE;
- group->priv->expander_style = GTK_EXPANDER_EXPANDED;
-
- label = gtk_label_new (NULL);
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
- gtk_container_add (GTK_CONTAINER (alignment), label);
- gtk_widget_show_all (alignment);
-
- gtk_widget_push_composite_child ();
- group->priv->header = gtk_button_new ();
- gtk_widget_set_composite_name (group->priv->header, "header");
- gtk_widget_pop_composite_child ();
-
- g_object_ref_sink (group->priv->header);
- gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE);
- gtk_container_add (GTK_CONTAINER (group->priv->header), alignment);
- gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group));
-
- gtk_tool_item_group_header_adjust_style (group);
-
- g_signal_connect_after (alignment, "expose-event",
- G_CALLBACK (gtk_tool_item_group_header_expose_event_cb),
- group);
- g_signal_connect_after (alignment, "size-request",
- G_CALLBACK (gtk_tool_item_group_header_size_request_cb),
- group);
-
- g_signal_connect (group->priv->header, "clicked",
- G_CALLBACK (gtk_tool_item_group_header_clicked_cb),
- group);
-}
-
-static void
-gtk_tool_item_group_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_NAME:
- gtk_tool_item_group_set_name (group, g_value_get_string (value));
- break;
-
- case PROP_COLLAPSED:
- gtk_tool_item_group_set_collapsed (group, g_value_get_boolean (value));
- break;
-
- case PROP_ELLIPSIZE:
- gtk_tool_item_group_set_ellipsize (group, g_value_get_enum (value));
- break;
- case PROP_RELIEF:
- gtk_tool_item_group_set_header_relief (group, g_value_get_enum(value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_NAME:
- g_value_set_string (value, gtk_tool_item_group_get_name (group));
- break;
-
- case PROP_COLLAPSED:
- g_value_set_boolean (value, gtk_tool_item_group_get_collapsed (group));
- break;
-
- case PROP_ELLIPSIZE:
- g_value_set_enum (value, gtk_tool_item_group_get_ellipsize (group));
- break;
-
- case PROP_RELIEF:
- g_value_set_enum (value, gtk_tool_item_group_get_header_relief (group));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_finalize (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- if (group->priv->children)
- {
- g_list_free (group->priv->children);
- group->priv->children = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_item_group_dispose (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- if (group->priv->toplevel)
- {
- /* disconnect focus tracking handler */
- g_signal_handler_disconnect (group->priv->toplevel,
- group->priv->focus_set_id);
-
- group->priv->focus_set_id = 0;
- group->priv->toplevel = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_item_group_get_item_size (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_get_item_size (GTK_TOOL_PALETTE (parent), item_size, homogeneous_only, requested_rows);
- else
- _gtk_tool_item_group_item_size_request (group, item_size, homogeneous_only, requested_rows);
-}
-
-static void
-gtk_tool_item_group_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkOrientation orientation;
- GtkRequisition item_size;
- gint requested_rows;
-
- if (group->priv->children && gtk_tool_item_group_get_name (group))
- {
- gtk_widget_size_request (group->priv->header, requisition);
- gtk_widget_show (group->priv->header);
- }
- else
- {
- requisition->width = requisition->height = 0;
- gtk_widget_hide (group->priv->header);
- }
-
- gtk_tool_item_group_get_item_size (group, &item_size, FALSE, &requested_rows);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- requisition->width = MAX (requisition->width, item_size.width);
- else
- requisition->height = MAX (requisition->height, item_size.height * requested_rows);
-
- requisition->width += border_width * 2;
- requisition->height += border_width * 2;
-}
-
-static gboolean
-gtk_tool_item_group_is_item_visible (GtkToolItemGroup *group,
- GtkToolItemGroupChild *child)
-{
- GtkToolbarStyle style;
- GtkOrientation orientation;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* horizontal tool palettes with text style support only homogeneous items */
- if (!child->homogeneous &&
- GTK_ORIENTATION_HORIZONTAL == orientation &&
- GTK_TOOLBAR_TEXT == style)
- return FALSE;
-
- return
- (GTK_WIDGET_VISIBLE (child->item)) &&
- (GTK_ORIENTATION_VERTICAL == orientation ?
- gtk_tool_item_get_visible_vertical (child->item) :
- gtk_tool_item_get_visible_horizontal (child->item));
-}
-
-static inline unsigned
-udiv (unsigned x,
- unsigned y)
-{
- return (x + y - 1) / y;
-}
-
-static void
-gtk_tool_item_group_real_size_query (GtkWidget *widget,
- GtkAllocation *allocation,
- GtkRequisition *inquery)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- gint min_rows;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- item_size.width = MIN (item_size.width, allocation->width);
- else
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = 0;
- item_area.height = 0;
-
- /* figure out the required columns (n_columns) and rows (n_rows) to place all items */
- if (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout)
- {
- guint n_columns;
- gint n_rows;
- GList *it;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- gboolean new_row = FALSE;
- gint row = -1;
- guint col = 0;
-
- item_area.width = allocation->width - 2 * border_width;
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- /* calculate required rows for n_columns columns */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
- n_rows = row + 2;
- }
- else
- {
- guint *row_min_width;
- gint row = -1;
- gboolean new_row = TRUE;
- guint col = 0, min_col, max_col = 0, all_items = 0;
- gint i;
-
- item_area.height = allocation->height - 2 * border_width;
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- row_min_width = g_new0 (guint, n_rows);
-
- /* calculate minimal and maximal required cols and minimal required rows */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- row_min_width[row] = 1;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- all_items++;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
-
- col += width;
- all_items += width;
-
- row_min_width[row] = MAX (row_min_width[row], width);
- }
-
- max_col = MAX (max_col, col);
- }
-
- /* calculate minimal required cols */
- min_col = udiv (all_items, n_rows);
-
- for (i = 0; i <= row; i++)
- {
- min_col = MAX (min_col, row_min_width[i]);
- }
-
- /* simple linear search for minimal required columns for the given maximal number of rows (n_rows) */
- for (n_columns = min_col; n_columns < max_col; n_columns ++)
- {
- new_row = TRUE;
- row = -1;
- /* calculate required rows for n_columns columns */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
-
- if (row < n_rows)
- break;
- }
- }
-
- item_area.width = item_size.width * n_columns;
- item_area.height = item_size.height * n_rows;
- }
-
- inquery->width = 0;
- inquery->height = 0;
-
- /* figure out header widget size */
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (group->priv->header, &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- inquery->height += child_requisition.height;
- else
- inquery->width += child_requisition.width;
- }
-
- /* report effective widget size */
- inquery->width += item_area.width + 2 * border_width;
- inquery->height += item_area.height + 2 * border_width;
-}
-
-static void
-gtk_tool_item_group_real_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkRequisition child_requisition;
- GtkAllocation child_allocation;
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- GList *it;
-
- gint n_columns, n_rows = 1;
- gint min_rows;
-
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* chain up */
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation);
-
- child_allocation.x = border_width;
- child_allocation.y = border_width;
-
- /* place the header widget */
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- gtk_widget_size_request (group->priv->header, &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- child_allocation.width = allocation->width;
- child_allocation.height = child_requisition.height;
- }
- else
- {
- child_allocation.width = child_requisition.width;
- child_allocation.height = allocation->height;
-
- if (GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - border_width - child_allocation.width;
- }
-
- gtk_widget_size_allocate (group->priv->header, &child_allocation);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- child_allocation.y += child_allocation.height;
- else if (GTK_TEXT_DIR_RTL != direction)
- child_allocation.x += child_allocation.width;
- else
- child_allocation.x = border_width;
- }
- else
- child_requisition.width = child_requisition.height = 0;
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- /* figure out the available columns and size of item_area */
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- item_size.width = MIN (item_size.width, allocation->width);
-
- item_area.width = allocation->width - 2 * border_width;
- item_area.height = allocation->height - 2 * border_width - child_requisition.height;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- item_size.width = item_area.width / n_columns;
- }
- else
- {
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = allocation->width - 2 * border_width - child_requisition.width;
- item_area.height = allocation->height - 2 * border_width;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- item_size.height = item_area.height / n_rows;
- }
-
- item_area.x = child_allocation.x;
- item_area.y = child_allocation.y;
-
- /* when expanded or in transition, place the tool items in a grid like layout */
- if (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout)
- {
- gint col = 0, row = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- gint col_child;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- {
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
-
- continue;
- }
-
- /* for non homogeneous widgets request the required size */
- child_requisition.width = 0;
-
- if (!child->homogeneous)
- {
- gtk_widget_size_request (GTK_WIDGET (child->item), &child_requisition);
- child_requisition.width = MIN (child_requisition.width, item_area.width);
- }
-
- /* select next row if at end of row */
- if (col > 0 && (child->new_row || (col * item_size.width) + MAX (child_requisition.width, item_size.width) > item_area.width))
- {
- row++;
- col = 0;
- child_allocation.y += child_allocation.height;
- }
-
- col_child = col;
-
- /* calculate the position and size of the item */
- if (!child->homogeneous)
- {
- gint col_width;
- gint width;
-
- if (!child->expand)
- col_width = udiv (child_requisition.width, item_size.width);
- else
- col_width = n_columns - col;
-
- width = col_width * item_size.width;
-
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - col_width);
-
- if (child->fill)
- {
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = width;
- }
- else
- {
- child_allocation.x =
- (item_area.x + col_child * item_size.width +
- (width - child_requisition.width) / 2);
- child_allocation.width = child_requisition.width;
- }
-
- col += col_width;
- }
- else
- {
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - 1);
-
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = item_size.width;
-
- col++;
- }
-
- child_allocation.height = item_size.height;
-
- gtk_widget_size_allocate (GTK_WIDGET (child->item), &child_allocation);
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), TRUE);
- }
-
- child_allocation.y += item_size.height;
- }
-
- /* or just hide all items, when collapsed */
-
- else
- {
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
- }
- }
-}
-
-static void
-gtk_tool_item_group_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- gtk_tool_item_group_real_size_allocate (widget, allocation);
-
- if (GTK_WIDGET_MAPPED (widget))
- gdk_window_invalidate_rect (widget->window, NULL, FALSE);
-}
-
-static void
-gtk_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED,
- GtkWidget *widget,
- gpointer user_data)
-{
- GtkAdjustment *adjustment;
- GtkWidget *p;
-
- /* Find this group's parent widget in the focused widget's anchestry. */
- for (p = widget; p; p = gtk_widget_get_parent (p))
- if (p == user_data)
- {
- p = gtk_widget_get_parent (p);
- break;
- }
-
- if (GTK_IS_TOOL_PALETTE (p))
- {
- /* Check that the focused widgets is fully visible within
- * the group's parent widget and make it visible otherwise. */
-
- adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p));
- adjustment = gtk_tool_palette_get_vadjustment (GTK_TOOL_PALETTE (p));
-
- if (adjustment)
- {
- int y;
-
- /* Handle vertical adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, NULL, &y) && y < 0)
- {
- y += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height);
- }
- else if (gtk_widget_translate_coordinates
- (widget, p, 0, widget->allocation.height, NULL, &y) &&
- y > p->allocation.height)
- {
- y += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y);
- }
- }
-
- adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p));
-
- if (adjustment)
- {
- int x;
-
- /* Handle horizontal adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, &x, NULL) && x < 0)
- {
- x += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width);
- }
- else if (gtk_widget_translate_coordinates
- (widget, p, widget->allocation.width, 0, &x, NULL) &&
- x > p->allocation.width)
- {
- x += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x);
- }
-
- return;
- }
- }
-}
-
-static void
-gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group,
- GtkWidget *toplevel)
-{
- if (toplevel != group->priv->toplevel)
- {
- if (group->priv->toplevel)
- {
- /* Disconnect focus tracking handler. */
- g_signal_handler_disconnect (group->priv->toplevel,
- group->priv->focus_set_id);
-
- group->priv->focus_set_id = 0;
- group->priv->toplevel = NULL;
- }
-
- if (toplevel)
- {
- /* Install focus tracking handler. We connect to the window's
- * set-focus signal instead of connecting to the focus signal of
- * each child to:
- *
- * 1) Reduce the number of signal handlers used.
- * 2) Avoid special handling for group headers.
- * 3) Catch focus grabs not only for direct children,
- * but also for nested widgets.
- */
- group->priv->focus_set_id =
- g_signal_connect (toplevel, "set-focus",
- G_CALLBACK (gtk_tool_item_group_set_focus_cb),
- group);
-
- group->priv->toplevel = toplevel;
- }
- }
-}
-
-static void
-gtk_tool_item_group_realize (GtkWidget *widget)
-{
- GtkWidget *toplevel_window;
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- GdkWindowAttr attributes;
- GdkDisplay *display;
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - border_width * 2;
- attributes.height = widget->allocation.height - border_width * 2;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
-
- display = gdk_drawable_get_display (widget->window);
-
- if (gdk_display_supports_composite (display))
- gdk_window_set_composited (widget->window, TRUE);
-
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_set_parent_window,
- widget->window);
-
- gtk_widget_queue_resize_no_redraw (widget);
-
- toplevel_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget),
- toplevel_window);
-}
-
-static void
-gtk_tool_item_group_unrealize (GtkWidget *widget)
-{
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget), NULL);
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->unrealize (widget);
-}
-
-static void
-gtk_tool_item_group_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
-{
- gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget));
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_set (widget, previous_style);
-}
-
-static void
-gtk_tool_item_group_add (GtkContainer *container,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM (widget));
-
- gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (container),
- GTK_TOOL_ITEM (widget), -1);
-}
-
-static void
-gtk_tool_item_group_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolItemGroup *group;
- GList *it;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- group = GTK_TOOL_ITEM_GROUP (container);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child_info = it->data;
-
- if ((GtkWidget *)child_info->item == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- g_free (child_info);
- group->priv->children = g_list_delete_link (group->priv->children, it);
-
- gtk_widget_queue_resize (GTK_WIDGET (container));
- break;
- }
- }
-}
-
-static void
-gtk_tool_item_group_forall (GtkContainer *container,
- gboolean internals,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GList *children;
-
- if (internals && group->priv->header)
- callback (group->priv->header, callback_data);
-
- children = group->priv->children;
- while (children)
- {
- GtkToolItemGroupChild *child = children->data;
- children = children->next; /* store pointer before call to callback
- because the child pointer is invalid if the
- child->item is removed from the item group
- in callback */
-
- callback (GTK_WIDGET (child->item), callback_data);
- }
-}
-
-static GType
-gtk_tool_item_group_child_type (GtkContainer *container G_GNUC_UNUSED)
-{
- return GTK_TYPE_TOOL_ITEM;
-}
-
-static GtkToolItemGroupChild *
-gtk_tool_item_group_get_child (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint *position,
- GList **link)
-{
- guint i;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), NULL);
-
- for (it = group->priv->children, i = 0; it != NULL; it = it->next, ++i)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (child->item == item)
- {
- if (position)
- *position = i;
-
- if (link)
- *link = it;
-
- return child;
- }
- }
-
- return NULL;
-}
-
-static void
-gtk_tool_item_group_get_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean *homogeneous,
- gboolean *expand,
- gboolean *fill,
- gboolean *new_row)
-{
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- if (expand)
- *expand = child->expand;
-
- if (homogeneous)
- *homogeneous = child->homogeneous;
-
- if (fill)
- *fill = child->fill;
-
- if (new_row)
- *new_row = child->new_row;
-}
-
-static void
-gtk_tool_item_group_set_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean homogeneous,
- gboolean expand,
- gboolean fill,
- gboolean new_row)
-{
- GtkToolItemGroupChild *child;
- gboolean changed = FALSE;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- gtk_widget_freeze_child_notify (GTK_WIDGET (item));
-
- if (child->homogeneous != homogeneous)
- {
- child->homogeneous = homogeneous;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "homogeneous");
- }
- if (child->expand != expand)
- {
- child->expand = expand;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "expand");
- }
- if (child->fill != fill)
- {
- child->fill = fill;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "fill");
- }
- if (child->new_row != new_row)
- {
- child->new_row = new_row;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "new-row");
- }
-
- gtk_widget_thaw_child_notify (GTK_WIDGET (item));
-
- if (changed && GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-static void
-gtk_tool_item_group_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- gtk_tool_item_group_set_item_packing (group, item,
- g_value_get_boolean (value),
- expand,
- fill,
- new_row);
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- g_value_get_boolean (value),
- fill,
- new_row);
- break;
-
- case CHILD_PROP_FILL:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- g_value_get_boolean (value),
- new_row);
- break;
-
- case CHILD_PROP_NEW_ROW:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- fill,
- g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_POSITION:
- gtk_tool_item_group_set_item_position (group, item, g_value_get_int (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- g_value_set_boolean (value, homogeneous);
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, expand);
- break;
-
- case CHILD_PROP_FILL:
- g_value_set_boolean (value, fill);
- break;
-
- case CHILD_PROP_NEW_ROW:
- g_value_set_boolean (value, new_row);
- break;
-
- case CHILD_PROP_POSITION:
- g_value_set_int (value, gtk_tool_item_group_get_item_position (group, item));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_class_init (GtkToolItemGroupClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_item_group_set_property;
- oclass->get_property = gtk_tool_item_group_get_property;
- oclass->finalize = gtk_tool_item_group_finalize;
- oclass->dispose = gtk_tool_item_group_dispose;
-
- wclass->size_request = gtk_tool_item_group_size_request;
- wclass->size_allocate = gtk_tool_item_group_size_allocate;
- wclass->realize = gtk_tool_item_group_realize;
- wclass->unrealize = gtk_tool_item_group_unrealize;
- wclass->style_set = gtk_tool_item_group_style_set;
- wclass->screen_changed = gtk_tool_item_group_screen_changed;
-
- cclass->add = gtk_tool_item_group_add;
- cclass->remove = gtk_tool_item_group_remove;
- cclass->forall = gtk_tool_item_group_forall;
- cclass->child_type = gtk_tool_item_group_child_type;
- cclass->set_child_property = gtk_tool_item_group_set_child_property;
- cclass->get_child_property = gtk_tool_item_group_get_child_property;
-
- g_object_class_install_property (oclass, PROP_NAME,
- g_param_spec_string ("name",
- P_("Name"),
- P_("The name of this item group"),
- DEFAULT_NAME,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_COLLAPSED,
- g_param_spec_boolean ("collapsed",
- P_("Collapsed"),
- P_("Wether the group has been collapsed and items are hidden"),
- DEFAULT_COLLAPSED,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("ellipsize",
- P_("ellipsize"),
- P_("Ellipsize for item group headers"),
- PANGO_TYPE_ELLIPSIZE_MODE, DEFAULT_ELLIPSIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("header-relief",
- P_("header-relif"),
- P_("Relief of the group header button"),
- GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_widget_class_install_style_property (wclass,
- g_param_spec_int ("expander-size",
- P_("Expander Size"),
- P_("Size of the expander arrow"),
- 0,
- G_MAXINT,
- DEFAULT_EXPANDER_SIZE,
- G_PARAM_READABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_widget_class_install_style_property (wclass,
- g_param_spec_int ("header-spacing",
- P_("Header Spacing"),
- P_("Spacing between expander arrow and caption"),
- 0,
- G_MAXINT,
- DEFAULT_HEADER_SPACING,
- G_PARAM_READABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_HOMOGENEOUS,
- g_param_spec_boolean ("homogeneous",
- P_("Homogeneous"),
- P_("Whether the item should be the same size as other homogeneous items"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item should receive extra space when the toolbar grows"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL,
- g_param_spec_boolean ("fill",
- P_("Fill"),
- P_("Whether the item should fill the avaiable space"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_NEW_ROW,
- g_param_spec_boolean ("new-row",
- P_("New Row"),
- P_("Whether the item should start a new row"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_POSITION,
- g_param_spec_int ("position",
- P_("Position"),
- P_("Position of the item within this group"),
- 0,
- G_MAXINT,
- 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_type_class_add_private (cls, sizeof (GtkToolItemGroupPrivate));
-}
-
-/**
- * gtk_tool_item_group_new:
- * @name: the name of the new group.
- *
- * Creates a new tool item group with name @name.
- *
- * Returns: a new #GtkToolItemGroup.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_item_group_new (const gchar *name)
-{
- return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "name", name, NULL);
-}
-
-/**
- * gtk_tool_item_group_set_name:
- * @group: an #GtkToolItemGroup.
- * @name: the new name of of the group.
- *
- * Sets the name of the tool item group. The name is displayed in the header
- * of the group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_name (GtkToolItemGroup *group,
- const gchar *name)
-{
- const gchar *current_name;
- GtkWidget *label;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- current_name = gtk_tool_item_group_get_name (group);
-
- if (current_name != name && (!current_name || !name || strcmp (current_name, name)))
- {
- label = gtk_tool_item_group_get_label (group);
- gtk_label_set_text (GTK_LABEL (label), name);
-
- if (name && group->priv->children)
- gtk_widget_show (group->priv->header);
- else
- gtk_widget_hide (group->priv->header);
-
- g_object_notify (G_OBJECT (group), "name");
- }
-}
-
-/**
- * gtk_tool_item_group_header_relief:
- * @group: an #GtkToolItemGroup.
- * @style: The GtkReliefStyle
- *
- * Set the button relief of the group header. See #gtk_button_set_relief for
- * details
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group,
- GtkReliefStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- gtk_button_set_relief (GTK_BUTTON(group->priv->header), style);
-}
-
-static gint64
-gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group)
-{
- GTimeVal now;
- g_source_get_current_time (group->priv->animation_timeout, &now);
- return (now.tv_sec * G_USEC_PER_SEC + now.tv_usec - group->priv->animation_start) / 1000;
-}
-
-static void
-gtk_tool_item_group_force_expose (GtkToolItemGroup *group)
-{
- if (GTK_WIDGET_REALIZED (group->priv->header))
- {
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- GdkRectangle area;
-
- /* Find the header button's arrow area... */
- area.x = alignment->allocation.x;
- area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2;
- area.height = group->priv->expander_size;
- area.width = group->priv->expander_size;
-
- /* ... and invalidated it to get it animated. */
- gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE);
- }
-
- if (GTK_WIDGET_REALIZED (group))
- {
- GtkWidget *widget = GTK_WIDGET (group);
- GtkWidget *parent = gtk_widget_get_parent (widget);
- int x, y, width, height;
-
- /* Find the tool item area button's arrow area... */
- width = widget->allocation.width;
- height = widget->allocation.height;
-
- gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
-
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- height -= group->priv->header->allocation.height;
- y += group->priv->header->allocation.height;
- }
-
- /* ... and invalidated it to get it animated. */
- gtk_widget_queue_draw_area (parent, x, y, width, height);
- }
-}
-
-static gboolean
-gtk_tool_item_group_animation_cb (gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- /* Enque this early to reduce number of expose events. */
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group));
-
- /* Figure out current style of the expander arrow. */
- if (group->priv->collapsed)
- {
- if (group->priv->expander_style == GTK_EXPANDER_EXPANDED)
- group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
- else
- group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
- }
- else
- {
- if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED)
- group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
- else
- group->priv->expander_style = GTK_EXPANDER_EXPANDED;
- }
-
- gtk_tool_item_group_force_expose (group);
-
- /* Finish animation when done. */
- if (timestamp >= ANIMATION_DURATION)
- group->priv->animation_timeout = NULL;
-
- /* Ensure that all composited windows and child windows are repainted, before
- * the parent widget gets its expose-event. This is needed to avoid heavy
- * rendering artifacts. GTK+ should take care about this issue by itself I
- * guess, but currently it doesn't. Also I don't understand the parameters
- * of this issue well enough yet, to file a bug report.
- */
- gdk_window_process_updates (GTK_WIDGET (group)->window, TRUE);
-
- return (group->priv->animation_timeout != NULL);
-}
-
-/**
- * gtk_tool_item_group_set_collapsed:
- * @group: an #GtkToolItemGroup.
- * @collapsed: whether the @group should be collapsed or expanded.
- *
- * Sets whether the @group should be collapsed or expanded.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group,
- gboolean collapsed)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- GtkWidget *parent;
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
- if (GTK_IS_TOOL_PALETTE (parent) && !collapsed)
- _gtk_tool_palette_set_expanding_child (GTK_TOOL_PALETTE (parent),
- GTK_WIDGET (group));
- if (collapsed != group->priv->collapsed)
- {
- if (group->priv->animation)
- {
- GTimeVal now;
-
- g_get_current_time (&now);
-
- if (group->priv->animation_timeout)
- g_source_destroy (group->priv->animation_timeout);
-
- group->priv->animation_start = (now.tv_sec * G_USEC_PER_SEC + now.tv_usec);
- group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT);
-
- g_source_set_callback (group->priv->animation_timeout,
- gtk_tool_item_group_animation_cb,
- group, NULL);
-
- g_source_attach (group->priv->animation_timeout, NULL);
- }
- else
- {
- group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
- gtk_tool_item_group_force_expose (group);
- }
- group->priv->collapsed = collapsed;
- g_object_notify (G_OBJECT (group), "collapsed");
- }
-}
-
-/**
- * gtk_tool_item_group_set_ellipsize:
- * @group: an #GtkToolItemGroup.
- * @ellipsize: the #PangoEllipsizeMode labels in @group should use.
- *
- * Sets the ellipsization mode which should be used by labels in @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group,
- PangoEllipsizeMode ellipsize)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- if (ellipsize != group->priv->ellipsize)
- {
- group->priv->ellipsize = ellipsize;
- gtk_tool_item_group_header_adjust_style (group);
- g_object_notify (G_OBJECT (group), "ellipsize");
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- _gtk_tool_item_group_palette_reconfigured (group);
-#endif
- }
-}
-
-/**
- * gtk_tool_item_group_get_name:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the name of @group.
- *
- * Returns: the name of @group. The name is an internal string of @group and must not be modified.
- *
- * Since: 2.18
- */
-G_CONST_RETURN gchar*
-gtk_tool_item_group_get_name (GtkToolItemGroup *group)
-{
- GtkWidget *label;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_NAME);
-
- label = gtk_tool_item_group_get_label (group);
- return gtk_label_get_text (GTK_LABEL (label));
-}
-
-/**
- * gtk_tool_item_group_get_collapsed:
- * @group: an GtkToolItemGroup.
- *
- * Gets whether @group is collapsed or expanded.
- *
- * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_COLLAPSED);
- return group->priv->collapsed;
-}
-
-/**
- * gtk_tool_item_group_get_ellipsize:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the ellipsization mode of @group.
- *
- * Returns: the #PangoEllipsizeMode of @group.
- *
- * Since: 2.18
- */
-PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_ELLIPSIZE);
- return group->priv->ellipsize;
-}
-
-/**
- * gtk_tool_item_group_get_header_relief:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the relief mode of the header button of @group.
- *
- * Returns: the #GtkReliefStyle
- *
- * Since: 2.18
- */
-GtkReliefStyle
-gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), GTK_RELIEF_NORMAL);
- return gtk_button_get_relief (GTK_BUTTON (group->priv->header));
-}
-
-/**
- * gtk_tool_item_group_insert:
- * @group: an #GtkToolItemGroup.
- * @item: the #GtkToolItem to insert into @group.
- * @position: the position of @item in @group, starting with 0. The position -1 means end of list.
- *
- * Inserts @item at @position in the list of children of @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_insert (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- GtkWidget *parent, *child_widget;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
- g_return_if_fail (position >= -1);
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- child = g_new (GtkToolItemGroupChild, 1);
- child->item = g_object_ref_sink (item);
- child->homogeneous = TRUE;
- child->expand = FALSE;
- child->fill = TRUE;
- child->new_row = FALSE;
-
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_child_set_drag_source (GTK_WIDGET (item), parent);
-
- child_widget = gtk_bin_get_child (GTK_BIN (item));
-
- if (GTK_IS_BUTTON (child_widget))
- gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), TRUE);
-
- gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_set_item_position:
- * @group: an #GtkToolItemGroup.
- * @item: the #GtkToolItem to move to a new position, should be a child of @group.
- * @position: the new position of @item in @group, starting with 0. The position -1 means end of list.
- *
- * Sets the position of @item in the list of children of @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_item_position (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- gint old_position;
- GList *link;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- g_return_if_fail (position >= -1);
-
- child = gtk_tool_item_group_get_child (group, item, &old_position, &link);
-
- g_return_if_fail (child != NULL);
-
- if (position == old_position)
- return;
-
- group->priv->children = g_list_delete_link (group->priv->children, link);
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- gtk_widget_child_notify (GTK_WIDGET (item), "position");
- if (GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_get_item_position:
- * @group: an #GtkToolItemGroup.
- * @item: a #GtkToolItem.
- *
- * Gets the position of @item in @group as index.
- *
- * Returns: the index of @item in @group or -1 if @item is no child of @group.
- *
- * Since: 2.18
- */
-gint
-gtk_tool_item_group_get_item_position (GtkToolItemGroup *group,
- GtkToolItem *item)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
-
- if (gtk_tool_item_group_get_child (group, item, &position, NULL))
- return position;
-
- return -1;
-}
-
-/**
- * gtk_tool_item_group_get_n_items:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the number of tool items in group.
- *
- * Returns: the number of tool items in group.
- *
- * Since: 2.18
- */
-guint
-gtk_tool_item_group_get_n_items (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), 0);
-
- return g_list_length (group->priv->children);
-}
-
-/**
- * gtk_tool_item_group_get_nth_item:
- * @group: an #GtkToolItemGroup.
- * @index: the index.
- *
- * Gets the tool item at index in group.
- *
- * Returns: the #GtkToolItem at index.
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group,
- guint index)
-{
- GtkToolItemGroupChild *child;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- child = g_list_nth_data (group->priv->children, index);
-
- return child != NULL ? child->item : NULL;
-}
-
-/**
- * gtk_tool_item_group_get_drop_item:
- * @group: an #GtkToolItemGroup.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the tool item at position (x, y).
- *
- * Returns: the #GtkToolItem at position (x, y).
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group,
- gint x,
- gint y)
-{
- GtkAllocation *allocation;
- GtkOrientation orientation;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- allocation = >K_WIDGET (group)->allocation;
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation->height, NULL);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- GtkToolItem *item = child->item;
- gint x0, y0;
-
- if (!item || !gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- allocation = >K_WIDGET (item)->allocation;
-
- x0 = x - allocation->x;
- y0 = y - allocation->y;
-
- if (x0 >= 0 && x0 < allocation->width &&
- y0 >= 0 && y0 < allocation->height)
- return item;
- }
-
- return NULL;
-}
-
-void
-_gtk_tool_item_group_item_size_request (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition child_requisition;
- GList *it;
- gint rows = 0;
- gboolean new_row = TRUE;
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (NULL != item_size);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- item_size->width = item_size->height = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (child->new_row || new_row)
- {
- rows++;
- new_row = FALSE;
- }
-
- if (!child->homogeneous && child->expand)
- new_row = TRUE;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &child_requisition);
-
- if (!homogeneous_only || child->homogeneous)
- item_size->width = MAX (item_size->width, child_requisition.width);
- item_size->height = MAX (item_size->height, child_requisition.height);
- }
-
- if (requested_rows)
- *requested_rows = rows;
-}
-
-void
-_gtk_tool_item_group_paint (GtkToolItemGroup *group,
- cairo_t *cr)
-{
- GtkWidget *widget = GTK_WIDGET (group);
-
- gdk_cairo_set_source_pixmap (cr, widget->window,
- widget->allocation.x,
- widget->allocation.y);
-
- if (group->priv->animation_timeout)
- {
- GtkOrientation orientation = gtk_tool_item_group_get_orientation (GTK_TOOL_SHELL (group));
- cairo_pattern_t *mask;
- gdouble v0, v1;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- v1 = widget->allocation.height;
- else
- v1 = widget->allocation.width;
-
- v0 = v1 - 256;
-
- if (!GTK_WIDGET_VISIBLE (group->priv->header))
- v0 = MAX (v0, 0);
- else if (GTK_ORIENTATION_VERTICAL == orientation)
- v0 = MAX (v0, group->priv->header->allocation.height);
- else
- v0 = MAX (v0, group->priv->header->allocation.width);
-
- v1 = MIN (v0 + 256, v1);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- v0 += widget->allocation.y;
- v1 += widget->allocation.y;
-
- mask = cairo_pattern_create_linear (0.0, v0, 0.0, v1);
- }
- else
- {
- v0 += widget->allocation.x;
- v1 += widget->allocation.x;
-
- mask = cairo_pattern_create_linear (v0, 0.0, v1, 0.0);
- }
-
- cairo_pattern_add_color_stop_rgba (mask, 0.00, 0.0, 0.0, 0.0, 1.00);
- cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.25);
- cairo_pattern_add_color_stop_rgba (mask, 0.50, 0.0, 0.0, 0.0, 0.10);
- cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.01);
- cairo_pattern_add_color_stop_rgba (mask, 1.00, 0.0, 0.0, 0.0, 0.00);
-
- cairo_mask (cr, mask);
- cairo_pattern_destroy (mask);
- }
- else
- cairo_paint (cr);
-}
-
-gint
-_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group,
- gint limit,
- gboolean vertical,
- gboolean animation)
-{
- GtkRequisition requisition;
-
- gtk_widget_size_request (GTK_WIDGET (group), &requisition);
-
- if (!group->priv->collapsed || group->priv->animation_timeout)
- {
- GtkAllocation allocation = { 0, 0, requisition.width, requisition.height };
- GtkRequisition inquery;
-
- if (vertical)
- allocation.width = limit;
- else
- allocation.height = limit;
-
- gtk_tool_item_group_real_size_query (GTK_WIDGET (group),
- &allocation, &inquery);
-
- if (vertical)
- inquery.height -= requisition.height;
- else
- inquery.width -= requisition.width;
-
- if (group->priv->animation_timeout && animation)
- {
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- timestamp = MIN (timestamp, ANIMATION_DURATION);
-
- if (group->priv->collapsed)
- timestamp = ANIMATION_DURATION - timestamp;
-
- if (vertical)
- {
- inquery.height *= timestamp;
- inquery.height /= ANIMATION_DURATION;
- }
- else
- {
- inquery.width *= timestamp;
- inquery.width /= ANIMATION_DURATION;
- }
- }
-
- if (vertical)
- requisition.height += inquery.height;
- else
- requisition.width += inquery.width;
- }
-
- return (vertical ? requisition.height : requisition.width);
-}
-
-gint
-_gtk_tool_item_group_get_height_for_width (GtkToolItemGroup *group,
- gint width)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, width, TRUE, group->priv->animation);
-}
-
-gint
-_gtk_tool_item_group_get_width_for_height (GtkToolItemGroup *group,
- gint height)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, height, FALSE, TRUE);
-}
-
-static void
-gtk_tool_palette_reconfigured_foreach_item (GtkWidget *child,
- gpointer data G_GNUC_UNUSED)
-{
- if (GTK_IS_TOOL_ITEM (child))
- gtk_tool_item_toolbar_reconfigured (GTK_TOOL_ITEM (child));
-}
-
-
-void
-_gtk_tool_item_group_palette_reconfigured (GtkToolItemGroup *group)
-{
- gtk_container_foreach (GTK_CONTAINER (group),
- gtk_tool_palette_reconfigured_foreach_item,
- NULL);
-
- gtk_tool_item_group_header_adjust_style (group);
-}
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Mathias Hasselmann
- * Jan Arne Petersen
- */
-
-#include "gtktoolpaletteprivate.h"
-
-#include <gtk/gtk.h>
-#include <math.h>
-#include <string.h>
-
-#define P_(msgid) (msgid)
-
-#define ANIMATION_TIMEOUT 50
-#define ANIMATION_DURATION (ANIMATION_TIMEOUT * 4)
-#define DEFAULT_ANIMATION_STATE TRUE
-#define DEFAULT_EXPANDER_SIZE 16
-#define DEFAULT_HEADER_SPACING 2
-
-#define DEFAULT_NAME NULL
-#define DEFAULT_COLLAPSED FALSE
-#define DEFAULT_ELLIPSIZE PANGO_ELLIPSIZE_NONE
-
-/**
- * SECTION:GtkToolItemGroup
- * @short_description: A sub container used in a tool palette
- * @include: gtktoolitemgroup.h
- *
- * An #GtkToolItemGroup is used together with #GtkToolPalette to add #GtkToolItem<!-- -->s to a palette like container
- * with different categories and drag and drop support.
- *
- * Since: 2.18
- */
-
-enum
-{
- PROP_NONE,
- PROP_NAME,
- PROP_COLLAPSED,
- PROP_ELLIPSIZE,
- PROP_RELIEF
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_HOMOGENEOUS,
- CHILD_PROP_EXPAND,
- CHILD_PROP_FILL,
- CHILD_PROP_NEW_ROW,
- CHILD_PROP_POSITION,
-};
-
-typedef struct _GtkToolItemGroupChild GtkToolItemGroupChild;
-
-struct _GtkToolItemGroupPrivate
-{
- GtkWidget *header;
-
- GList *children;
-
- gboolean animation;
- gint64 animation_start;
- GSource *animation_timeout;
- GtkExpanderStyle expander_style;
- gint expander_size;
- gint header_spacing;
- PangoEllipsizeMode ellipsize;
-
- gulong focus_set_id;
- GtkWidget *toplevel;
-
- GtkSettings *settings;
- gulong settings_connection;
-
- guint collapsed : 1;
-};
-
-struct _GtkToolItemGroupChild
-{
- GtkToolItem *item;
-
- guint homogeneous : 1;
- guint expand : 1;
- guint fill : 1;
- guint new_row : 1;
-};
-
-static void gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface);
-
-G_DEFINE_TYPE_WITH_CODE (GtkToolItemGroup, gtk_tool_item_group, GTK_TYPE_CONTAINER,
-G_IMPLEMENT_INTERFACE (GTK_TYPE_TOOL_SHELL, gtk_tool_item_group_tool_shell_init));
-
-static GtkWidget*
-gtk_tool_item_group_get_alignment (GtkToolItemGroup *group)
-{
- return gtk_bin_get_child (GTK_BIN (group->priv->header));
-}
-
-static GtkWidget*
-gtk_tool_item_group_get_label (GtkToolItemGroup *group)
-{
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- return gtk_bin_get_child (GTK_BIN (alignment));
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent));
-
- return GTK_ORIENTATION_VERTICAL;
-}
-
-static GtkToolbarStyle
-gtk_tool_item_group_get_style (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_style (GTK_TOOL_PALETTE (parent));
-
- return GTK_TOOLBAR_ICONS;
-}
-
-static GtkIconSize
-gtk_tool_item_group_get_icon_size (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return gtk_tool_palette_get_icon_size (GTK_TOOL_PALETTE (parent));
-
- return GTK_ICON_SIZE_SMALL_TOOLBAR;
-}
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
-
-static PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize_mode (GtkToolShell *shell)
-{
- return GTK_TOOL_ITEM_GROUP (shell)->priv->ellipsize;
-}
-
-static gfloat
-gtk_tool_item_group_get_text_alignment (GtkToolShell *shell)
-{
- if (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell) ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell))
- return 0.0;
-
- return 0.5;
-}
-
-static GtkOrientation
-gtk_tool_item_group_get_text_orientation (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- {
- GtkOrientation orientation = gtk_tool_palette_get_orientation (GTK_TOOL_PALETTE (parent));
- if (GTK_ORIENTATION_HORIZONTAL == orientation &&
- (GTK_TOOLBAR_TEXT == gtk_tool_item_group_get_style (shell)/* ||
- GTK_TOOLBAR_BOTH_HORIZ == gtk_tool_item_group_get_style (shell)*/))
- return GTK_ORIENTATION_VERTICAL;
- }
-
- return GTK_ORIENTATION_HORIZONTAL;
-}
-
-static GtkSizeGroup *
-gtk_tool_item_group_get_text_size_group (GtkToolShell *shell)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (shell));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- return _gtk_tool_palette_get_size_group (GTK_TOOL_PALETTE (parent));
-
- return NULL;
-}
-
-#endif
-
-static void
-animation_change_notify (GtkToolItemGroup *group)
-{
- GtkSettings *settings = group->priv->settings;
- gboolean animation;
-
- if (settings)
- g_object_get (settings,
- "gtk-enable-animations", &animation,
- NULL);
- else
- animation = DEFAULT_ANIMATION_STATE;
-
- group->priv->animation = animation;
-}
-
-static void
-gtk_tool_item_group_settings_change_notify (GtkSettings *settings,
- const GParamSpec *pspec,
- GtkToolItemGroup *group)
-{
- if (! strcmp (pspec->name, "gtk-enable-animations"))
- {
- animation_change_notify (group);
- }
-}
-
-static void
-gtk_tool_item_group_screen_changed (GtkWidget *widget,
- GdkScreen *previous_screen)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkToolItemGroupPrivate* priv = group->priv;
- GtkSettings *old_settings = priv->settings;
- GtkSettings *settings;
-
- if (gtk_widget_has_screen (GTK_WIDGET (group)))
- settings = gtk_widget_get_settings (GTK_WIDGET (group));
- else
- settings = NULL;
-
- if (settings == old_settings)
- return;
-
- if (old_settings)
- {
- g_signal_handler_disconnect (old_settings, priv->settings_connection);
- g_object_unref (old_settings);
- }
-
- if (settings)
- {
- priv->settings_connection =
- g_signal_connect (settings, "notify",
- G_CALLBACK (gtk_tool_item_group_settings_change_notify),
- group);
- priv->settings = g_object_ref (settings);
- }
- else
- priv->settings = NULL;
-
- animation_change_notify (group);
-}
-
-static void
-gtk_tool_item_group_tool_shell_init (GtkToolShellIface *iface)
-{
- iface->get_icon_size = gtk_tool_item_group_get_icon_size;
- iface->get_orientation = gtk_tool_item_group_get_orientation;
- iface->get_style = gtk_tool_item_group_get_style;
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- iface->get_text_alignment = gtk_tool_item_group_get_text_alignment;
- iface->get_text_orientation = gtk_tool_item_group_get_text_orientation;
- iface->get_text_size_group = gtk_tool_item_group_get_text_size_group;
- iface->get_ellipsize_mode = gtk_tool_item_group_get_ellipsize_mode;
-#endif
-}
-
-static gboolean
-gtk_tool_item_group_header_expose_event_cb (GtkWidget *widget,
- GdkEventExpose *event,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkExpanderStyle expander_style;
- GtkOrientation orientation;
- gint x, y;
- GtkTextDirection direction;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- expander_style = group->priv->expander_style;
- direction = gtk_widget_get_direction (widget);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- if (GTK_TEXT_DIR_RTL == direction)
- x = widget->allocation.x + widget->allocation.width - group->priv->expander_size / 2;
- else
- x = widget->allocation.x + group->priv->expander_size / 2;
- y = widget->allocation.y + widget->allocation.height / 2;
- }
- else
- {
- x = widget->allocation.x + widget->allocation.width / 2;
- y = widget->allocation.y + group->priv->expander_size / 2;
-
- /* Unfortunatly gtk_paint_expander() doesn't support rotated drawing
- * modes. Luckily the following shady arithmetics produce the desired
- * result. */
- expander_style = GTK_EXPANDER_EXPANDED - expander_style; /* XXX */
- }
-
- gtk_paint_expander (widget->style, widget->window,
- group->priv->header->state,
- &event->area, GTK_WIDGET (group),
- "tool-palette-header", x, y,
- expander_style);
-
- return FALSE;
-}
-
-static void
-gtk_tool_item_group_header_size_request_cb (GtkWidget *widget G_GNUC_UNUSED,
- GtkRequisition *requisition,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- requisition->height = MAX (requisition->height, group->priv->expander_size);
-}
-
-static void
-gtk_tool_item_group_header_clicked_cb (GtkButton *button G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- GtkWidget *parent = gtk_widget_get_parent (data);
-
- if (group->priv->collapsed ||
- !GTK_IS_TOOL_PALETTE (parent) ||
- !gtk_tool_palette_get_exclusive (GTK_TOOL_PALETTE (parent), data))
- gtk_tool_item_group_set_collapsed (group, !group->priv->collapsed);
-}
-
-static void
-gtk_tool_item_group_header_adjust_style (GtkToolItemGroup *group)
-{
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- GtkWidget *label = gtk_bin_get_child (GTK_BIN (alignment));
- GtkWidget *widget = GTK_WIDGET (group);
- gint dx = 0, dy = 0;
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- gtk_widget_style_get (widget,
- "header-spacing", &group->priv->header_spacing,
- "expander-size", &group->priv->expander_size,
- NULL);
-
- switch (gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group)))
- {
- case GTK_ORIENTATION_HORIZONTAL:
- dy = group->priv->header_spacing + group->priv->expander_size;
- gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_NONE);
- if (GTK_TEXT_DIR_RTL == direction)
- gtk_label_set_angle (GTK_LABEL (label), -90);
- else
- gtk_label_set_angle (GTK_LABEL (label), 90);
- break;
-
- case GTK_ORIENTATION_VERTICAL:
- dx = group->priv->header_spacing + group->priv->expander_size;
- gtk_label_set_ellipsize (GTK_LABEL (label), group->priv->ellipsize);
- gtk_label_set_angle (GTK_LABEL (label), 0);
- break;
- }
-
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), dy, 0, dx, 0);
-}
-
-static void
-gtk_tool_item_group_init (GtkToolItemGroup *group)
-{
- GtkWidget *alignment;
- GtkWidget *label;
-
- gtk_widget_set_redraw_on_allocate (GTK_WIDGET (group), FALSE);
-
- group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group,
- GTK_TYPE_TOOL_ITEM_GROUP,
- GtkToolItemGroupPrivate);
-
- group->priv->children = NULL;
- group->priv->header_spacing = DEFAULT_HEADER_SPACING;
- group->priv->expander_size = DEFAULT_EXPANDER_SIZE;
- group->priv->expander_style = GTK_EXPANDER_EXPANDED;
-
- label = gtk_label_new (NULL);
- gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
- alignment = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
- gtk_container_add (GTK_CONTAINER (alignment), label);
- gtk_widget_show_all (alignment);
-
- gtk_widget_push_composite_child ();
- group->priv->header = gtk_button_new ();
- gtk_widget_set_composite_name (group->priv->header, "header");
- gtk_widget_pop_composite_child ();
-
- g_object_ref_sink (group->priv->header);
- gtk_button_set_focus_on_click (GTK_BUTTON (group->priv->header), FALSE);
- gtk_container_add (GTK_CONTAINER (group->priv->header), alignment);
- gtk_widget_set_parent (group->priv->header, GTK_WIDGET (group));
-
- gtk_tool_item_group_header_adjust_style (group);
-
- g_signal_connect_after (alignment, "expose-event",
- G_CALLBACK (gtk_tool_item_group_header_expose_event_cb),
- group);
- g_signal_connect_after (alignment, "size-request",
- G_CALLBACK (gtk_tool_item_group_header_size_request_cb),
- group);
-
- g_signal_connect (group->priv->header, "clicked",
- G_CALLBACK (gtk_tool_item_group_header_clicked_cb),
- group);
-}
-
-static void
-gtk_tool_item_group_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_NAME:
- gtk_tool_item_group_set_name (group, g_value_get_string (value));
- break;
-
- case PROP_COLLAPSED:
- gtk_tool_item_group_set_collapsed (group, g_value_get_boolean (value));
- break;
-
- case PROP_ELLIPSIZE:
- gtk_tool_item_group_set_ellipsize (group, g_value_get_enum (value));
- break;
- case PROP_RELIEF:
- gtk_tool_item_group_set_header_relief (group, g_value_get_enum(value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- switch (prop_id)
- {
- case PROP_NAME:
- g_value_set_string (value, gtk_tool_item_group_get_name (group));
- break;
-
- case PROP_COLLAPSED:
- g_value_set_boolean (value, gtk_tool_item_group_get_collapsed (group));
- break;
-
- case PROP_ELLIPSIZE:
- g_value_set_enum (value, gtk_tool_item_group_get_ellipsize (group));
- break;
-
- case PROP_RELIEF:
- g_value_set_enum (value, gtk_tool_item_group_get_header_relief (group));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_finalize (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- if (group->priv->children)
- {
- g_list_free (group->priv->children);
- group->priv->children = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_item_group_dispose (GObject *object)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (object);
-
- if (group->priv->toplevel)
- {
- /* disconnect focus tracking handler */
- g_signal_handler_disconnect (group->priv->toplevel,
- group->priv->focus_set_id);
-
- group->priv->focus_set_id = 0;
- group->priv->toplevel = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_item_group_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_item_group_get_item_size (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkWidget *parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_get_item_size (GTK_TOOL_PALETTE (parent), item_size, homogeneous_only, requested_rows);
- else
- _gtk_tool_item_group_item_size_request (group, item_size, homogeneous_only, requested_rows);
-}
-
-static void
-gtk_tool_item_group_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkOrientation orientation;
- GtkRequisition item_size;
- gint requested_rows;
-
- if (group->priv->children && gtk_tool_item_group_get_name (group))
- {
- gtk_widget_size_request (group->priv->header, requisition);
- gtk_widget_show (group->priv->header);
- }
- else
- {
- requisition->width = requisition->height = 0;
- gtk_widget_hide (group->priv->header);
- }
-
- gtk_tool_item_group_get_item_size (group, &item_size, FALSE, &requested_rows);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- requisition->width = MAX (requisition->width, item_size.width);
- else
- requisition->height = MAX (requisition->height, item_size.height * requested_rows);
-
- requisition->width += border_width * 2;
- requisition->height += border_width * 2;
-}
-
-static gboolean
-gtk_tool_item_group_is_item_visible (GtkToolItemGroup *group,
- GtkToolItemGroupChild *child)
-{
- GtkToolbarStyle style;
- GtkOrientation orientation;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* horizontal tool palettes with text style support only homogeneous items */
- if (!child->homogeneous &&
- GTK_ORIENTATION_HORIZONTAL == orientation &&
- GTK_TOOLBAR_TEXT == style)
- return FALSE;
-
- return
- (GTK_WIDGET_VISIBLE (child->item)) &&
- (GTK_ORIENTATION_VERTICAL == orientation ?
- gtk_tool_item_get_visible_vertical (child->item) :
- gtk_tool_item_get_visible_horizontal (child->item));
-}
-
-static inline unsigned
-udiv (unsigned x,
- unsigned y)
-{
- return (x + y - 1) / y;
-}
-
-static void
-gtk_tool_item_group_real_size_query (GtkWidget *widget,
- GtkAllocation *allocation,
- GtkRequisition *inquery)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- gint min_rows;
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- item_size.width = MIN (item_size.width, allocation->width);
- else
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = 0;
- item_area.height = 0;
-
- /* figure out the required columns (n_columns) and rows (n_rows) to place all items */
- if (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout)
- {
- guint n_columns;
- gint n_rows;
- GList *it;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- gboolean new_row = FALSE;
- gint row = -1;
- guint col = 0;
-
- item_area.width = allocation->width - 2 * border_width;
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- /* calculate required rows for n_columns columns */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
- n_rows = row + 2;
- }
- else
- {
- guint *row_min_width;
- gint row = -1;
- gboolean new_row = TRUE;
- guint col = 0, min_col, max_col = 0, all_items = 0;
- gint i;
-
- item_area.height = allocation->height - 2 * border_width;
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- row_min_width = g_new0 (guint, n_rows);
-
- /* calculate minimal and maximal required cols and minimal required rows */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- row_min_width[row] = 1;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- all_items++;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
-
- col += width;
- all_items += width;
-
- row_min_width[row] = MAX (row_min_width[row], width);
- }
-
- max_col = MAX (max_col, col);
- }
-
- /* calculate minimal required cols */
- min_col = udiv (all_items, n_rows);
-
- for (i = 0; i <= row; i++)
- {
- min_col = MAX (min_col, row_min_width[i]);
- }
-
- /* simple linear search for minimal required columns for the given maximal number of rows (n_rows) */
- for (n_columns = min_col; n_columns < max_col; n_columns ++)
- {
- new_row = TRUE;
- row = -1;
- /* calculate required rows for n_columns columns */
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (new_row || child->new_row)
- {
- new_row = FALSE;
- row++;
- col = 0;
- }
-
- if (child->expand)
- new_row = TRUE;
-
- if (child->homogeneous)
- {
- col++;
- if (col >= n_columns)
- new_row = TRUE;
- }
- else
- {
- GtkRequisition req = {0, 0};
- guint width;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &req);
-
- width = udiv (req.width, item_size.width);
- col += width;
-
- if (col > n_columns)
- row++;
-
- col = width;
-
- if (col >= n_columns)
- new_row = TRUE;
- }
- }
-
- if (row < n_rows)
- break;
- }
- }
-
- item_area.width = item_size.width * n_columns;
- item_area.height = item_size.height * n_rows;
- }
-
- inquery->width = 0;
- inquery->height = 0;
-
- /* figure out header widget size */
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- GtkRequisition child_requisition;
-
- gtk_widget_size_request (group->priv->header, &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- inquery->height += child_requisition.height;
- else
- inquery->width += child_requisition.width;
- }
-
- /* report effective widget size */
- inquery->width += item_area.width + 2 * border_width;
- inquery->height += item_area.height + 2 * border_width;
-}
-
-static void
-gtk_tool_item_group_real_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (widget);
- GtkRequisition child_requisition;
- GtkAllocation child_allocation;
-
- GtkRequisition item_size;
- GtkAllocation item_area;
-
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- GList *it;
-
- gint n_columns, n_rows = 1;
- gint min_rows;
-
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- /* chain up */
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->size_allocate (widget, allocation);
-
- child_allocation.x = border_width;
- child_allocation.y = border_width;
-
- /* place the header widget */
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- gtk_widget_size_request (group->priv->header, &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- child_allocation.width = allocation->width;
- child_allocation.height = child_requisition.height;
- }
- else
- {
- child_allocation.width = child_requisition.width;
- child_allocation.height = allocation->height;
-
- if (GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - border_width - child_allocation.width;
- }
-
- gtk_widget_size_allocate (group->priv->header, &child_allocation);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- child_allocation.y += child_allocation.height;
- else if (GTK_TEXT_DIR_RTL != direction)
- child_allocation.x += child_allocation.width;
- else
- child_allocation.x = border_width;
- }
- else
- child_requisition.width = child_requisition.height = 0;
-
- /* figure out the size of homogeneous items */
- gtk_tool_item_group_get_item_size (group, &item_size, TRUE, &min_rows);
-
- /* figure out the available columns and size of item_area */
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- item_size.width = MIN (item_size.width, allocation->width);
-
- item_area.width = allocation->width - 2 * border_width;
- item_area.height = allocation->height - 2 * border_width - child_requisition.height;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
-
- item_size.width = item_area.width / n_columns;
- }
- else
- {
- item_size.height = MIN (item_size.height, allocation->height);
-
- item_area.width = allocation->width - 2 * border_width - child_requisition.width;
- item_area.height = allocation->height - 2 * border_width;
-
- n_columns = MAX (item_area.width / item_size.width, 1);
- n_rows = MAX (item_area.height / item_size.height, min_rows);
-
- item_size.height = item_area.height / n_rows;
- }
-
- item_area.x = child_allocation.x;
- item_area.y = child_allocation.y;
-
- /* when expanded or in transition, place the tool items in a grid like layout */
- if (!group->priv->collapsed || !group->priv->animation || group->priv->animation_timeout)
- {
- gint col = 0, row = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- gint col_child;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- {
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
-
- continue;
- }
-
- /* for non homogeneous widgets request the required size */
- child_requisition.width = 0;
-
- if (!child->homogeneous)
- {
- gtk_widget_size_request (GTK_WIDGET (child->item), &child_requisition);
- child_requisition.width = MIN (child_requisition.width, item_area.width);
- }
-
- /* select next row if at end of row */
- if (col > 0 && (child->new_row || (col * item_size.width) + MAX (child_requisition.width, item_size.width) > item_area.width))
- {
- row++;
- col = 0;
- child_allocation.y += child_allocation.height;
- }
-
- col_child = col;
-
- /* calculate the position and size of the item */
- if (!child->homogeneous)
- {
- gint col_width;
- gint width;
-
- if (!child->expand)
- col_width = udiv (child_requisition.width, item_size.width);
- else
- col_width = n_columns - col;
-
- width = col_width * item_size.width;
-
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - col_width);
-
- if (child->fill)
- {
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = width;
- }
- else
- {
- child_allocation.x =
- (item_area.x + col_child * item_size.width +
- (width - child_requisition.width) / 2);
- child_allocation.width = child_requisition.width;
- }
-
- col += col_width;
- }
- else
- {
- if (GTK_TEXT_DIR_RTL == direction)
- col_child = (n_columns - col - 1);
-
- child_allocation.x = item_area.x + col_child * item_size.width;
- child_allocation.width = item_size.width;
-
- col++;
- }
-
- child_allocation.height = item_size.height;
-
- gtk_widget_size_allocate (GTK_WIDGET (child->item), &child_allocation);
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), TRUE);
- }
-
- child_allocation.y += item_size.height;
- }
-
- /* or just hide all items, when collapsed */
-
- else
- {
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- gtk_widget_set_child_visible (GTK_WIDGET (child->item), FALSE);
- }
- }
-}
-
-static void
-gtk_tool_item_group_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- gtk_tool_item_group_real_size_allocate (widget, allocation);
-
- if (GTK_WIDGET_MAPPED (widget))
- gdk_window_invalidate_rect (widget->window, NULL, FALSE);
-}
-
-static void
-gtk_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED,
- GtkWidget *widget,
- gpointer user_data)
-{
- GtkAdjustment *adjustment;
- GtkWidget *p;
-
- /* Find this group's parent widget in the focused widget's anchestry. */
- for (p = widget; p; p = gtk_widget_get_parent (p))
- if (p == user_data)
- {
- p = gtk_widget_get_parent (p);
- break;
- }
-
- if (GTK_IS_TOOL_PALETTE (p))
- {
- /* Check that the focused widgets is fully visible within
- * the group's parent widget and make it visible otherwise. */
-
- adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p));
- adjustment = gtk_tool_palette_get_vadjustment (GTK_TOOL_PALETTE (p));
-
- if (adjustment)
- {
- int y;
-
- /* Handle vertical adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, NULL, &y) && y < 0)
- {
- y += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height);
- }
- else if (gtk_widget_translate_coordinates
- (widget, p, 0, widget->allocation.height, NULL, &y) &&
- y > p->allocation.height)
- {
- y += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y);
- }
- }
-
- adjustment = gtk_tool_palette_get_hadjustment (GTK_TOOL_PALETTE (p));
-
- if (adjustment)
- {
- int x;
-
- /* Handle horizontal adjustment. */
- if (gtk_widget_translate_coordinates
- (widget, p, 0, 0, &x, NULL) && x < 0)
- {
- x += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width);
- }
- else if (gtk_widget_translate_coordinates
- (widget, p, widget->allocation.width, 0, &x, NULL) &&
- x > p->allocation.width)
- {
- x += adjustment->value;
- gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x);
- }
-
- return;
- }
- }
-}
-
-static void
-gtk_tool_item_group_set_toplevel_window (GtkToolItemGroup *group,
- GtkWidget *toplevel)
-{
- if (toplevel != group->priv->toplevel)
- {
- if (group->priv->toplevel)
- {
- /* Disconnect focus tracking handler. */
- g_signal_handler_disconnect (group->priv->toplevel,
- group->priv->focus_set_id);
-
- group->priv->focus_set_id = 0;
- group->priv->toplevel = NULL;
- }
-
- if (toplevel)
- {
- /* Install focus tracking handler. We connect to the window's
- * set-focus signal instead of connecting to the focus signal of
- * each child to:
- *
- * 1) Reduce the number of signal handlers used.
- * 2) Avoid special handling for group headers.
- * 3) Catch focus grabs not only for direct children,
- * but also for nested widgets.
- */
- group->priv->focus_set_id =
- g_signal_connect (toplevel, "set-focus",
- G_CALLBACK (gtk_tool_item_group_set_focus_cb),
- group);
-
- group->priv->toplevel = toplevel;
- }
- }
-}
-
-static void
-gtk_tool_item_group_realize (GtkWidget *widget)
-{
- GtkWidget *toplevel_window;
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- GdkWindowAttr attributes;
- GdkDisplay *display;
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - border_width * 2;
- attributes.height = widget->allocation.height - border_width * 2;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
-
- display = gdk_drawable_get_display (widget->window);
-
- if (gdk_display_supports_composite (display))
- gdk_window_set_composited (widget->window, TRUE);
-
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_set_parent_window,
- widget->window);
-
- gtk_widget_queue_resize_no_redraw (widget);
-
- toplevel_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget),
- toplevel_window);
-}
-
-static void
-gtk_tool_item_group_unrealize (GtkWidget *widget)
-{
- gtk_tool_item_group_set_toplevel_window (GTK_TOOL_ITEM_GROUP (widget), NULL);
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->unrealize (widget);
-}
-
-static void
-gtk_tool_item_group_style_set (GtkWidget *widget,
- GtkStyle *previous_style)
-{
- gtk_tool_item_group_header_adjust_style (GTK_TOOL_ITEM_GROUP (widget));
- GTK_WIDGET_CLASS (gtk_tool_item_group_parent_class)->style_set (widget, previous_style);
-}
-
-static void
-gtk_tool_item_group_add (GtkContainer *container,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM (widget));
-
- gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (container),
- GTK_TOOL_ITEM (widget), -1);
-}
-
-static void
-gtk_tool_item_group_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolItemGroup *group;
- GList *it;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (container));
- group = GTK_TOOL_ITEM_GROUP (container);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child_info = it->data;
-
- if ((GtkWidget *)child_info->item == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- g_free (child_info);
- group->priv->children = g_list_delete_link (group->priv->children, it);
-
- gtk_widget_queue_resize (GTK_WIDGET (container));
- break;
- }
- }
-}
-
-static void
-gtk_tool_item_group_forall (GtkContainer *container,
- gboolean internals,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GList *children;
-
- if (internals && group->priv->header)
- callback (group->priv->header, callback_data);
-
- children = group->priv->children;
- while (children)
- {
- GtkToolItemGroupChild *child = children->data;
- children = children->next; /* store pointer before call to callback
- because the child pointer is invalid if the
- child->item is removed from the item group
- in callback */
-
- callback (GTK_WIDGET (child->item), callback_data);
- }
-}
-
-static GType
-gtk_tool_item_group_child_type (GtkContainer *container G_GNUC_UNUSED)
-{
- return GTK_TYPE_TOOL_ITEM;
-}
-
-static GtkToolItemGroupChild *
-gtk_tool_item_group_get_child (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint *position,
- GList **link)
-{
- guint i;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), NULL);
-
- for (it = group->priv->children, i = 0; it != NULL; it = it->next, ++i)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (child->item == item)
- {
- if (position)
- *position = i;
-
- if (link)
- *link = it;
-
- return child;
- }
- }
-
- return NULL;
-}
-
-static void
-gtk_tool_item_group_get_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean *homogeneous,
- gboolean *expand,
- gboolean *fill,
- gboolean *new_row)
-{
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- if (expand)
- *expand = child->expand;
-
- if (homogeneous)
- *homogeneous = child->homogeneous;
-
- if (fill)
- *fill = child->fill;
-
- if (new_row)
- *new_row = child->new_row;
-}
-
-static void
-gtk_tool_item_group_set_item_packing (GtkToolItemGroup *group,
- GtkToolItem *item,
- gboolean homogeneous,
- gboolean expand,
- gboolean fill,
- gboolean new_row)
-{
- GtkToolItemGroupChild *child;
- gboolean changed = FALSE;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- child = gtk_tool_item_group_get_child (group, item, NULL, NULL);
- if (!child)
- return;
-
- gtk_widget_freeze_child_notify (GTK_WIDGET (item));
-
- if (child->homogeneous != homogeneous)
- {
- child->homogeneous = homogeneous;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "homogeneous");
- }
- if (child->expand != expand)
- {
- child->expand = expand;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "expand");
- }
- if (child->fill != fill)
- {
- child->fill = fill;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "fill");
- }
- if (child->new_row != new_row)
- {
- child->new_row = new_row;
- changed = TRUE;
- gtk_widget_child_notify (GTK_WIDGET (item), "new-row");
- }
-
- gtk_widget_thaw_child_notify (GTK_WIDGET (item));
-
- if (changed && GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-static void
-gtk_tool_item_group_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- gtk_tool_item_group_set_item_packing (group, item,
- g_value_get_boolean (value),
- expand,
- fill,
- new_row);
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- g_value_get_boolean (value),
- fill,
- new_row);
- break;
-
- case CHILD_PROP_FILL:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- g_value_get_boolean (value),
- new_row);
- break;
-
- case CHILD_PROP_NEW_ROW:
- gtk_tool_item_group_set_item_packing (group, item,
- homogeneous,
- expand,
- fill,
- g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_POSITION:
- gtk_tool_item_group_set_item_position (group, item, g_value_get_int (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (container);
- GtkToolItem *item = GTK_TOOL_ITEM (child);
- gboolean homogeneous, expand, fill, new_row;
-
- if (prop_id != CHILD_PROP_POSITION)
- gtk_tool_item_group_get_item_packing (group, item,
- &homogeneous,
- &expand,
- &fill,
- &new_row);
-
- switch (prop_id)
- {
- case CHILD_PROP_HOMOGENEOUS:
- g_value_set_boolean (value, homogeneous);
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, expand);
- break;
-
- case CHILD_PROP_FILL:
- g_value_set_boolean (value, fill);
- break;
-
- case CHILD_PROP_NEW_ROW:
- g_value_set_boolean (value, new_row);
- break;
-
- case CHILD_PROP_POSITION:
- g_value_set_int (value, gtk_tool_item_group_get_item_position (group, item));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_item_group_class_init (GtkToolItemGroupClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_item_group_set_property;
- oclass->get_property = gtk_tool_item_group_get_property;
- oclass->finalize = gtk_tool_item_group_finalize;
- oclass->dispose = gtk_tool_item_group_dispose;
-
- wclass->size_request = gtk_tool_item_group_size_request;
- wclass->size_allocate = gtk_tool_item_group_size_allocate;
- wclass->realize = gtk_tool_item_group_realize;
- wclass->unrealize = gtk_tool_item_group_unrealize;
- wclass->style_set = gtk_tool_item_group_style_set;
- wclass->screen_changed = gtk_tool_item_group_screen_changed;
-
- cclass->add = gtk_tool_item_group_add;
- cclass->remove = gtk_tool_item_group_remove;
- cclass->forall = gtk_tool_item_group_forall;
- cclass->child_type = gtk_tool_item_group_child_type;
- cclass->set_child_property = gtk_tool_item_group_set_child_property;
- cclass->get_child_property = gtk_tool_item_group_get_child_property;
-
- g_object_class_install_property (oclass, PROP_NAME,
- g_param_spec_string ("name",
- P_("Name"),
- P_("The name of this item group"),
- DEFAULT_NAME,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_COLLAPSED,
- g_param_spec_boolean ("collapsed",
- P_("Collapsed"),
- P_("Wether the group has been collapsed and items are hidden"),
- DEFAULT_COLLAPSED,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("ellipsize",
- P_("ellipsize"),
- P_("Ellipsize for item group headers"),
- PANGO_TYPE_ELLIPSIZE_MODE, DEFAULT_ELLIPSIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ELLIPSIZE,
- g_param_spec_enum ("header-relief",
- P_("header-relif"),
- P_("Relief of the group header button"),
- GTK_TYPE_RELIEF_STYLE, GTK_RELIEF_NORMAL,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_widget_class_install_style_property (wclass,
- g_param_spec_int ("expander-size",
- P_("Expander Size"),
- P_("Size of the expander arrow"),
- 0,
- G_MAXINT,
- DEFAULT_EXPANDER_SIZE,
- G_PARAM_READABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_widget_class_install_style_property (wclass,
- g_param_spec_int ("header-spacing",
- P_("Header Spacing"),
- P_("Spacing between expander arrow and caption"),
- 0,
- G_MAXINT,
- DEFAULT_HEADER_SPACING,
- G_PARAM_READABLE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_HOMOGENEOUS,
- g_param_spec_boolean ("homogeneous",
- P_("Homogeneous"),
- P_("Whether the item should be the same size as other homogeneous items"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item should receive extra space when the toolbar grows"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_FILL,
- g_param_spec_boolean ("fill",
- P_("Fill"),
- P_("Whether the item should fill the avaiable space"),
- TRUE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_NEW_ROW,
- g_param_spec_boolean ("new-row",
- P_("New Row"),
- P_("Whether the item should start a new row"),
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_POSITION,
- g_param_spec_int ("position",
- P_("Position"),
- P_("Position of the item within this group"),
- 0,
- G_MAXINT,
- 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_type_class_add_private (cls, sizeof (GtkToolItemGroupPrivate));
-}
-
-/**
- * gtk_tool_item_group_new:
- * @name: the name of the new group.
- *
- * Creates a new tool item group with name @name.
- *
- * Returns: a new #GtkToolItemGroup.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_item_group_new (const gchar *name)
-{
- return g_object_new (GTK_TYPE_TOOL_ITEM_GROUP, "name", name, NULL);
-}
-
-/**
- * gtk_tool_item_group_set_name:
- * @group: an #GtkToolItemGroup.
- * @name: the new name of of the group.
- *
- * Sets the name of the tool item group. The name is displayed in the header
- * of the group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_name (GtkToolItemGroup *group,
- const gchar *name)
-{
- const gchar *current_name;
- GtkWidget *label;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- current_name = gtk_tool_item_group_get_name (group);
-
- if (current_name != name && (!current_name || !name || strcmp (current_name, name)))
- {
- label = gtk_tool_item_group_get_label (group);
- gtk_label_set_text (GTK_LABEL (label), name);
-
- if (name && group->priv->children)
- gtk_widget_show (group->priv->header);
- else
- gtk_widget_hide (group->priv->header);
-
- g_object_notify (G_OBJECT (group), "name");
- }
-}
-
-/**
- * gtk_tool_item_group_header_relief:
- * @group: an #GtkToolItemGroup.
- * @style: The GtkReliefStyle
- *
- * Set the button relief of the group header. See #gtk_button_set_relief for
- * details
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_header_relief (GtkToolItemGroup *group,
- GtkReliefStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- gtk_button_set_relief (GTK_BUTTON(group->priv->header), style);
-}
-
-static gint64
-gtk_tool_item_group_get_animation_timestamp (GtkToolItemGroup *group)
-{
- GTimeVal now;
- g_source_get_current_time (group->priv->animation_timeout, &now);
- return (now.tv_sec * G_USEC_PER_SEC + now.tv_usec - group->priv->animation_start) / 1000;
-}
-
-static void
-gtk_tool_item_group_force_expose (GtkToolItemGroup *group)
-{
- if (GTK_WIDGET_REALIZED (group->priv->header))
- {
- GtkWidget *alignment = gtk_tool_item_group_get_alignment (group);
- GdkRectangle area;
-
- /* Find the header button's arrow area... */
- area.x = alignment->allocation.x;
- area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2;
- area.height = group->priv->expander_size;
- area.width = group->priv->expander_size;
-
- /* ... and invalidated it to get it animated. */
- gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE);
- }
-
- if (GTK_WIDGET_REALIZED (group))
- {
- GtkWidget *widget = GTK_WIDGET (group);
- GtkWidget *parent = gtk_widget_get_parent (widget);
- int x, y, width, height;
-
- /* Find the tool item area button's arrow area... */
- width = widget->allocation.width;
- height = widget->allocation.height;
-
- gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
-
- if (GTK_WIDGET_VISIBLE (group->priv->header))
- {
- height -= group->priv->header->allocation.height;
- y += group->priv->header->allocation.height;
- }
-
- /* ... and invalidated it to get it animated. */
- gtk_widget_queue_draw_area (parent, x, y, width, height);
- }
-}
-
-static gboolean
-gtk_tool_item_group_animation_cb (gpointer data)
-{
- GtkToolItemGroup *group = GTK_TOOL_ITEM_GROUP (data);
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- /* Enque this early to reduce number of expose events. */
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group));
-
- /* Figure out current style of the expander arrow. */
- if (group->priv->collapsed)
- {
- if (group->priv->expander_style == GTK_EXPANDER_EXPANDED)
- group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
- else
- group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
- }
- else
- {
- if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED)
- group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
- else
- group->priv->expander_style = GTK_EXPANDER_EXPANDED;
- }
-
- gtk_tool_item_group_force_expose (group);
-
- /* Finish animation when done. */
- if (timestamp >= ANIMATION_DURATION)
- group->priv->animation_timeout = NULL;
-
- /* Ensure that all composited windows and child windows are repainted, before
- * the parent widget gets its expose-event. This is needed to avoid heavy
- * rendering artifacts. GTK+ should take care about this issue by itself I
- * guess, but currently it doesn't. Also I don't understand the parameters
- * of this issue well enough yet, to file a bug report.
- */
- gdk_window_process_updates (GTK_WIDGET (group)->window, TRUE);
-
- return (group->priv->animation_timeout != NULL);
-}
-
-/**
- * gtk_tool_item_group_set_collapsed:
- * @group: an #GtkToolItemGroup.
- * @collapsed: whether the @group should be collapsed or expanded.
- *
- * Sets whether the @group should be collapsed or expanded.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_collapsed (GtkToolItemGroup *group,
- gboolean collapsed)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- GtkWidget *parent;
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
- if (GTK_IS_TOOL_PALETTE (parent) && !collapsed)
- _gtk_tool_palette_set_expanding_child (GTK_TOOL_PALETTE (parent),
- GTK_WIDGET (group));
- if (collapsed != group->priv->collapsed)
- {
- if (group->priv->animation)
- {
- GTimeVal now;
-
- g_get_current_time (&now);
-
- if (group->priv->animation_timeout)
- g_source_destroy (group->priv->animation_timeout);
-
- group->priv->animation_start = (now.tv_sec * G_USEC_PER_SEC + now.tv_usec);
- group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT);
-
- g_source_set_callback (group->priv->animation_timeout,
- gtk_tool_item_group_animation_cb,
- group, NULL);
-
- g_source_attach (group->priv->animation_timeout, NULL);
- }
- else
- {
- group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
- gtk_tool_item_group_force_expose (group);
- }
- group->priv->collapsed = collapsed;
- g_object_notify (G_OBJECT (group), "collapsed");
- }
-}
-
-/**
- * gtk_tool_item_group_set_ellipsize:
- * @group: an #GtkToolItemGroup.
- * @ellipsize: the #PangoEllipsizeMode labels in @group should use.
- *
- * Sets the ellipsization mode which should be used by labels in @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_ellipsize (GtkToolItemGroup *group,
- PangoEllipsizeMode ellipsize)
-{
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- if (ellipsize != group->priv->ellipsize)
- {
- group->priv->ellipsize = ellipsize;
- gtk_tool_item_group_header_adjust_style (group);
- g_object_notify (G_OBJECT (group), "ellipsize");
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- _gtk_tool_item_group_palette_reconfigured (group);
-#endif
- }
-}
-
-/**
- * gtk_tool_item_group_get_name:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the name of @group.
- *
- * Returns: the name of @group. The name is an internal string of @group and must not be modified.
- *
- * Since: 2.18
- */
-G_CONST_RETURN gchar*
-gtk_tool_item_group_get_name (GtkToolItemGroup *group)
-{
- GtkWidget *label;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_NAME);
-
- label = gtk_tool_item_group_get_label (group);
- return gtk_label_get_text (GTK_LABEL (label));
-}
-
-/**
- * gtk_tool_item_group_get_collapsed:
- * @group: an GtkToolItemGroup.
- *
- * Gets whether @group is collapsed or expanded.
- *
- * Returns: %TRUE if @group is collapsed, %FALSE if it is expanded.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_item_group_get_collapsed (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_COLLAPSED);
- return group->priv->collapsed;
-}
-
-/**
- * gtk_tool_item_group_get_ellipsize:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the ellipsization mode of @group.
- *
- * Returns: the #PangoEllipsizeMode of @group.
- *
- * Since: 2.18
- */
-PangoEllipsizeMode
-gtk_tool_item_group_get_ellipsize (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_ELLIPSIZE);
- return group->priv->ellipsize;
-}
-
-/**
- * gtk_tool_item_group_get_header_relief:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the relief mode of the header button of @group.
- *
- * Returns: the #GtkReliefStyle
- *
- * Since: 2.18
- */
-GtkReliefStyle
-gtk_tool_item_group_get_header_relief (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), GTK_RELIEF_NORMAL);
- return gtk_button_get_relief (GTK_BUTTON (group->priv->header));
-}
-
-/**
- * gtk_tool_item_group_insert:
- * @group: an #GtkToolItemGroup.
- * @item: the #GtkToolItem to insert into @group.
- * @position: the position of @item in @group, starting with 0. The position -1 means end of list.
- *
- * Inserts @item at @position in the list of children of @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_insert (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- GtkWidget *parent, *child_widget;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
- g_return_if_fail (position >= -1);
-
- parent = gtk_widget_get_parent (GTK_WIDGET (group));
-
- child = g_new (GtkToolItemGroupChild, 1);
- child->item = g_object_ref_sink (item);
- child->homogeneous = TRUE;
- child->expand = FALSE;
- child->fill = TRUE;
- child->new_row = FALSE;
-
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- if (GTK_IS_TOOL_PALETTE (parent))
- _gtk_tool_palette_child_set_drag_source (GTK_WIDGET (item), parent);
-
- child_widget = gtk_bin_get_child (GTK_BIN (item));
-
- if (GTK_IS_BUTTON (child_widget))
- gtk_button_set_focus_on_click (GTK_BUTTON (child_widget), TRUE);
-
- gtk_widget_set_parent (GTK_WIDGET (item), GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_set_item_position:
- * @group: an #GtkToolItemGroup.
- * @item: the #GtkToolItem to move to a new position, should be a child of @group.
- * @position: the new position of @item in @group, starting with 0. The position -1 means end of list.
- *
- * Sets the position of @item in the list of children of @group.
- *
- * Since: 2.18
- */
-void
-gtk_tool_item_group_set_item_position (GtkToolItemGroup *group,
- GtkToolItem *item,
- gint position)
-{
- gint old_position;
- GList *link;
- GtkToolItemGroupChild *child;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (GTK_IS_TOOL_ITEM (item));
-
- g_return_if_fail (position >= -1);
-
- child = gtk_tool_item_group_get_child (group, item, &old_position, &link);
-
- g_return_if_fail (child != NULL);
-
- if (position == old_position)
- return;
-
- group->priv->children = g_list_delete_link (group->priv->children, link);
- group->priv->children = g_list_insert (group->priv->children, child, position);
-
- gtk_widget_child_notify (GTK_WIDGET (item), "position");
- if (GTK_WIDGET_VISIBLE (group) && GTK_WIDGET_VISIBLE (item))
- gtk_widget_queue_resize (GTK_WIDGET (group));
-}
-
-/**
- * gtk_tool_item_group_get_item_position:
- * @group: an #GtkToolItemGroup.
- * @item: a #GtkToolItem.
- *
- * Gets the position of @item in @group as index.
- *
- * Returns: the index of @item in @group or -1 if @item is no child of @group.
- *
- * Since: 2.18
- */
-gint
-gtk_tool_item_group_get_item_position (GtkToolItemGroup *group,
- GtkToolItem *item)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (item), -1);
-
- if (gtk_tool_item_group_get_child (group, item, &position, NULL))
- return position;
-
- return -1;
-}
-
-/**
- * gtk_tool_item_group_get_n_items:
- * @group: an #GtkToolItemGroup.
- *
- * Gets the number of tool items in group.
- *
- * Returns: the number of tool items in group.
- *
- * Since: 2.18
- */
-guint
-gtk_tool_item_group_get_n_items (GtkToolItemGroup *group)
-{
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), 0);
-
- return g_list_length (group->priv->children);
-}
-
-/**
- * gtk_tool_item_group_get_nth_item:
- * @group: an #GtkToolItemGroup.
- * @index: the index.
- *
- * Gets the tool item at index in group.
- *
- * Returns: the #GtkToolItem at index.
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_item_group_get_nth_item (GtkToolItemGroup *group,
- guint index)
-{
- GtkToolItemGroupChild *child;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- child = g_list_nth_data (group->priv->children, index);
-
- return child != NULL ? child->item : NULL;
-}
-
-/**
- * gtk_tool_item_group_get_drop_item:
- * @group: an #GtkToolItemGroup.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the tool item at position (x, y).
- *
- * Returns: the #GtkToolItem at position (x, y).
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_item_group_get_drop_item (GtkToolItemGroup *group,
- gint x,
- gint y)
-{
- GtkAllocation *allocation;
- GtkOrientation orientation;
- GList *it;
-
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), NULL);
-
- allocation = >K_WIDGET (group)->allocation;
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
-
- g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation->height, NULL);
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
- GtkToolItem *item = child->item;
- gint x0, y0;
-
- if (!item || !gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- allocation = >K_WIDGET (item)->allocation;
-
- x0 = x - allocation->x;
- y0 = y - allocation->y;
-
- if (x0 >= 0 && x0 < allocation->width &&
- y0 >= 0 && y0 < allocation->height)
- return item;
- }
-
- return NULL;
-}
-
-void
-_gtk_tool_item_group_item_size_request (GtkToolItemGroup *group,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition child_requisition;
- GList *it;
- gint rows = 0;
- gboolean new_row = TRUE;
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
- g_return_if_fail (NULL != item_size);
-
- orientation = gtk_tool_shell_get_orientation (GTK_TOOL_SHELL (group));
- style = gtk_tool_shell_get_style (GTK_TOOL_SHELL (group));
-
- item_size->width = item_size->height = 0;
-
- for (it = group->priv->children; it != NULL; it = it->next)
- {
- GtkToolItemGroupChild *child = it->data;
-
- if (!gtk_tool_item_group_is_item_visible (group, child))
- continue;
-
- if (child->new_row || new_row)
- {
- rows++;
- new_row = FALSE;
- }
-
- if (!child->homogeneous && child->expand)
- new_row = TRUE;
-
- gtk_widget_size_request (GTK_WIDGET (child->item), &child_requisition);
-
- if (!homogeneous_only || child->homogeneous)
- item_size->width = MAX (item_size->width, child_requisition.width);
- item_size->height = MAX (item_size->height, child_requisition.height);
- }
-
- if (requested_rows)
- *requested_rows = rows;
-}
-
-void
-_gtk_tool_item_group_paint (GtkToolItemGroup *group,
- cairo_t *cr)
-{
- GtkWidget *widget = GTK_WIDGET (group);
-
- gdk_cairo_set_source_pixmap (cr, widget->window,
- widget->allocation.x,
- widget->allocation.y);
-
- if (group->priv->animation_timeout)
- {
- GtkOrientation orientation = gtk_tool_item_group_get_orientation (GTK_TOOL_SHELL (group));
- cairo_pattern_t *mask;
- gdouble v0, v1;
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- v1 = widget->allocation.height;
- else
- v1 = widget->allocation.width;
-
- v0 = v1 - 256;
-
- if (!GTK_WIDGET_VISIBLE (group->priv->header))
- v0 = MAX (v0, 0);
- else if (GTK_ORIENTATION_VERTICAL == orientation)
- v0 = MAX (v0, group->priv->header->allocation.height);
- else
- v0 = MAX (v0, group->priv->header->allocation.width);
-
- v1 = MIN (v0 + 256, v1);
-
- if (GTK_ORIENTATION_VERTICAL == orientation)
- {
- v0 += widget->allocation.y;
- v1 += widget->allocation.y;
-
- mask = cairo_pattern_create_linear (0.0, v0, 0.0, v1);
- }
- else
- {
- v0 += widget->allocation.x;
- v1 += widget->allocation.x;
-
- mask = cairo_pattern_create_linear (v0, 0.0, v1, 0.0);
- }
-
- cairo_pattern_add_color_stop_rgba (mask, 0.00, 0.0, 0.0, 0.0, 1.00);
- cairo_pattern_add_color_stop_rgba (mask, 0.25, 0.0, 0.0, 0.0, 0.25);
- cairo_pattern_add_color_stop_rgba (mask, 0.50, 0.0, 0.0, 0.0, 0.10);
- cairo_pattern_add_color_stop_rgba (mask, 0.75, 0.0, 0.0, 0.0, 0.01);
- cairo_pattern_add_color_stop_rgba (mask, 1.00, 0.0, 0.0, 0.0, 0.00);
-
- cairo_mask (cr, mask);
- cairo_pattern_destroy (mask);
- }
- else
- cairo_paint (cr);
-}
-
-gint
-_gtk_tool_item_group_get_size_for_limit (GtkToolItemGroup *group,
- gint limit,
- gboolean vertical,
- gboolean animation)
-{
- GtkRequisition requisition;
-
- gtk_widget_size_request (GTK_WIDGET (group), &requisition);
-
- if (!group->priv->collapsed || group->priv->animation_timeout)
- {
- GtkAllocation allocation = { 0, 0, requisition.width, requisition.height };
- GtkRequisition inquery;
-
- if (vertical)
- allocation.width = limit;
- else
- allocation.height = limit;
-
- gtk_tool_item_group_real_size_query (GTK_WIDGET (group),
- &allocation, &inquery);
-
- if (vertical)
- inquery.height -= requisition.height;
- else
- inquery.width -= requisition.width;
-
- if (group->priv->animation_timeout && animation)
- {
- gint64 timestamp = gtk_tool_item_group_get_animation_timestamp (group);
-
- timestamp = MIN (timestamp, ANIMATION_DURATION);
-
- if (group->priv->collapsed)
- timestamp = ANIMATION_DURATION - timestamp;
-
- if (vertical)
- {
- inquery.height *= timestamp;
- inquery.height /= ANIMATION_DURATION;
- }
- else
- {
- inquery.width *= timestamp;
- inquery.width /= ANIMATION_DURATION;
- }
- }
-
- if (vertical)
- requisition.height += inquery.height;
- else
- requisition.width += inquery.width;
- }
-
- return (vertical ? requisition.height : requisition.width);
-}
-
-gint
-_gtk_tool_item_group_get_height_for_width (GtkToolItemGroup *group,
- gint width)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, width, TRUE, group->priv->animation);
-}
-
-gint
-_gtk_tool_item_group_get_width_for_height (GtkToolItemGroup *group,
- gint height)
-{
- return _gtk_tool_item_group_get_size_for_limit (group, height, FALSE, TRUE);
-}
-
-static void
-gtk_tool_palette_reconfigured_foreach_item (GtkWidget *child,
- gpointer data G_GNUC_UNUSED)
-{
- if (GTK_IS_TOOL_ITEM (child))
- gtk_tool_item_toolbar_reconfigured (GTK_TOOL_ITEM (child));
-}
-
-
-void
-_gtk_tool_item_group_palette_reconfigured (GtkToolItemGroup *group)
-{
- gtk_container_foreach (GTK_CONTAINER (group),
- gtk_tool_palette_reconfigured_foreach_item,
- NULL);
-
- gtk_tool_item_group_header_adjust_style (group);
-}
+++ /dev/null
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Mathias Hasselmann
- */
-
-#include "gtktoolpaletteprivate.h"
-#include "gtkmarshalers.h"
-
-#include <gtk/gtk.h>
-#include <string.h>
-
-#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR
-#define DEFAULT_ORIENTATION GTK_ORIENTATION_VERTICAL
-#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_ICONS
-
-#define DEFAULT_CHILD_EXCLUSIVE FALSE
-#define DEFAULT_CHILD_EXPAND FALSE
-
-#define P_(msgid) (msgid)
-
-/**
- * SECTION:GtkToolPalette
- * @short_description: A tool palette with categories
- * @include: gtktoolpalette.h
- *
- * An #GtkToolPalette allows it to add #GtkToolItem<!-- -->s to a palette like container
- * with different categories and drag and drop support.
- *
- * An #GtkToolPalette is created with a call to gtk_tool_palette_new().
- *
- * #GtkToolItem<!-- -->s cannot be added directly to an #GtkToolPalette, instead they
- * are added to an #GtkToolItemGroup which can than be added to an #GtkToolPalette. To add
- * an #GtkToolItemGroup to an #GtkToolPalette use gtk_container_add().
- *
- * |[
- * GtkWidget *palette, *group;
- * GtkToolItem *item;
- *
- * palette = gtk_tool_palette_new ();
- * group = gtk_tool_item_group_new (_("Test Category"));
- * gtk_container_add (GTK_CONTAINER (palette), group);
- *
- * item = gtk_tool_button_new_from_stock (GTK_STOCK_OK);
- * gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
- * ]|
- *
- * The easiest way to use drag and drop with GtkToolPalette is to call gtk_tool_palette_add_drag_dest()
- * with the desired drag source @palette and the desired drag target @widget. Than gtk_tool_palette_get_drag_item()
- * can be used to get the dragged item in the #GtkWidget::drag-data-received signal handler of the drag target.
- *
- * |[
- * static void
- * passive_canvas_drag_data_received (GtkWidget *widget,
- * GdkDragContext *context,
- * gint x,
- * gint y,
- * GtkSelectionData *selection,
- * guint info,
- * guint time,
- * gpointer data)
- * {
- * GtkWidget *palette;
- * GtkWidget *item;
- *
- * /<!-- -->* Get the dragged item *<!-- -->/
- * palette = gtk_widget_get_ancestor (gtk_drag_get_source_widget (context), GTK_TYPE_TOOL_PALETTE);
- * if (palette != NULL)
- * item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette), selection);
- *
- * /<!-- -->* Do something with item *<!-- -->/
- * }
- *
- * GtkWidget *target, palette;
- *
- * palette = gtk_tool_palette_new ();
- * target = gtk_drawing_area_new ();
- *
- * g_signal_connect (G_OBJECT (target), "drag-data-received",
- * G_CALLBACK (passive_canvas_drag_data_received), NULL);
- * gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette), target,
- * GTK_DEST_DEFAULT_ALL,
- * GTK_TOOL_PALETTE_DRAG_ITEMS,
- * GDK_ACTION_COPY);
- * ]|
- *
- * Since: 2.18
- */
-
-typedef struct _GtkToolItemGroupInfo GtkToolItemGroupInfo;
-typedef struct _GtkToolPaletteDragData GtkToolPaletteDragData;
-
-enum
-{
- PROP_NONE,
- PROP_ICON_SIZE,
- PROP_ORIENTATION,
- PROP_TOOLBAR_STYLE,
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_EXCLUSIVE,
- CHILD_PROP_EXPAND,
-};
-
-struct _GtkToolItemGroupInfo
-{
- GtkToolItemGroup *widget;
-
- guint notify_collapsed;
- guint exclusive : 1;
- guint expand : 1;
-};
-
-struct _GtkToolPalettePrivate
-{
- GtkToolItemGroupInfo *groups;
- gsize groups_size;
- gsize groups_length;
-
- GtkAdjustment *hadjustment;
- GtkAdjustment *vadjustment;
-
- GtkIconSize icon_size;
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- GtkWidget *expanding_child;
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- GtkSizeGroup *text_size_group;
-#endif
-
- guint sparse_groups : 1;
- guint drag_source : 2;
-};
-
-struct _GtkToolPaletteDragData
-{
- GtkToolPalette *palette;
- GtkWidget *item;
-};
-
-static GdkAtom dnd_target_atom_item = GDK_NONE;
-static GdkAtom dnd_target_atom_group = GDK_NONE;
-
-static const GtkTargetEntry dnd_targets[] =
-{
- { "application/x-GTK-tool-palette-item", GTK_TARGET_SAME_APP, 0 },
- { "application/x-GTK-tool-palette-group", GTK_TARGET_SAME_APP, 0 },
-};
-
-G_DEFINE_TYPE (GtkToolPalette,
- gtk_tool_palette,
- GTK_TYPE_CONTAINER);
-
-static void
-gtk_tool_palette_init (GtkToolPalette *palette)
-{
- palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette,
- GTK_TYPE_TOOL_PALETTE,
- GtkToolPalettePrivate);
-
- palette->priv->groups_size = 4;
- palette->priv->groups_length = 0;
- palette->priv->groups = g_new0 (GtkToolItemGroupInfo, palette->priv->groups_size);
-
- palette->priv->icon_size = DEFAULT_ICON_SIZE;
- palette->priv->orientation = DEFAULT_ORIENTATION;
- palette->priv->style = DEFAULT_TOOLBAR_STYLE;
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- palette->priv->text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
-#endif
-}
-
-static void
-gtk_tool_palette_reconfigured (GtkToolPalette *palette)
-{
- guint i;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- if (palette->priv->groups[i].widget)
- _gtk_tool_item_group_palette_reconfigured (palette->priv->groups[i].widget);
- }
-
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- switch (prop_id)
- {
- case PROP_ICON_SIZE:
- if ((guint) g_value_get_enum (value) != palette->priv->icon_size)
- {
- palette->priv->icon_size = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- case PROP_ORIENTATION:
- if ((guint) g_value_get_enum (value) != palette->priv->orientation)
- {
- palette->priv->orientation = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- case PROP_TOOLBAR_STYLE:
- if ((guint) g_value_get_enum (value) != palette->priv->style)
- {
- palette->priv->style = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- switch (prop_id)
- {
- case PROP_ICON_SIZE:
- g_value_set_enum (value, gtk_tool_palette_get_icon_size (palette));
- break;
-
- case PROP_ORIENTATION:
- g_value_set_enum (value, gtk_tool_palette_get_orientation (palette));
- break;
-
- case PROP_TOOLBAR_STYLE:
- g_value_set_enum (value, gtk_tool_palette_get_style (palette));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_dispose (GObject *object)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
- guint i;
-
- if (palette->priv->hadjustment)
- {
- g_object_unref (palette->priv->hadjustment);
- palette->priv->hadjustment = NULL;
- }
-
- if (palette->priv->vadjustment)
- {
- g_object_unref (palette->priv->vadjustment);
- palette->priv->vadjustment = NULL;
- }
-
- for (i = 0; i < palette->priv->groups_size; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (group->notify_collapsed)
- {
- g_signal_handler_disconnect (group->widget, group->notify_collapsed);
- group->notify_collapsed = 0;
- }
- }
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- if (palette->priv->text_size_group)
- {
- g_object_unref (palette->priv->text_size_group);
- palette->priv->text_size_group = NULL;
- }
-#endif
-
- G_OBJECT_CLASS (gtk_tool_palette_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_palette_finalize (GObject *object)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- if (palette->priv->groups)
- {
- palette->priv->groups_length = 0;
- g_free (palette->priv->groups);
- palette->priv->groups = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_palette_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_palette_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GtkRequisition child_requisition;
- guint i;
-
- requisition->width = 0;
- requisition->height = 0;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (!group->widget)
- continue;
-
- gtk_widget_size_request (GTK_WIDGET (group->widget), &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- requisition->width = MAX (requisition->width, child_requisition.width);
- requisition->height += child_requisition.height;
- }
- else
- {
- requisition->width += child_requisition.width;
- requisition->height = MAX (requisition->height, child_requisition.height);
- }
- }
-
- requisition->width += border_width * 2;
- requisition->height += border_width * 2;
-}
-
-static void
-gtk_tool_palette_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GtkAdjustment *adjustment = NULL;
- GtkAllocation child_allocation;
-
- gint n_expand_groups = 0;
- gint remaining_space = 0;
- gint expand_space = 0;
-
- gint page_start, page_size = 0;
- gint offset = 0;
- guint i;
-
- gint min_offset = -1, max_offset = -1;
-
- gint x;
-
- gint *group_sizes = g_newa(gint, palette->priv->groups_length);
-
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- GTK_WIDGET_CLASS (gtk_tool_palette_parent_class)->size_allocate (widget, allocation);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- adjustment = palette->priv->vadjustment;
- page_size = allocation->height;
- }
- else
- {
- adjustment = palette->priv->hadjustment;
- page_size = allocation->width;
- }
-
- if (adjustment)
- offset = gtk_adjustment_get_value (adjustment);
- if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
- GTK_TEXT_DIR_RTL == direction)
- offset = -offset;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.width = allocation->width - border_width * 2;
- else
- child_allocation.height = allocation->height - border_width * 2;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- remaining_space = allocation->height;
- else
- remaining_space = allocation->width;
-
- /* figure out the required size of all groups to be able to distribute the
- * remaining space on allocation */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- gint size;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- if (gtk_tool_item_group_get_n_items (group->widget))
- {
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- size = _gtk_tool_item_group_get_height_for_width (group->widget, child_allocation.width);
- else
- size = _gtk_tool_item_group_get_width_for_height (group->widget, child_allocation.height);
-
- if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget))
- n_expand_groups += 1;
- }
- else
- size = 0;
-
- remaining_space -= size;
- group_sizes[i] = size;
-
- /* if the widget is currently expanding an offset which allows to display as much of the
- * widget as possible is calculated */
- if (widget == palette->priv->expanding_child)
- {
- gint limit =
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
- child_allocation.width : child_allocation.height;
-
- gint real_size;
- guint j;
-
- min_offset = 0;
-
- for (j = 0; j < i; ++j)
- min_offset += group_sizes[j];
-
- max_offset = min_offset + group_sizes[i];
-
- real_size = _gtk_tool_item_group_get_size_for_limit
- (GTK_TOOL_ITEM_GROUP (widget), limit,
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation,
- FALSE);
-
- if (size == real_size)
- palette->priv->expanding_child = NULL;
- }
- }
-
- if (n_expand_groups > 0)
- {
- remaining_space = MAX (0, remaining_space);
- expand_space = remaining_space / n_expand_groups;
- }
-
- if (max_offset != -1)
- {
- gint limit =
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
- allocation->height : allocation->width;
-
- offset = MIN (MAX (offset, max_offset - limit), min_offset);
- }
-
- if (remaining_space > 0)
- offset = 0;
-
- x = border_width;
- child_allocation.y = border_width;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.y -= offset;
- else
- x -= offset;
-
- /* allocate all groups at the calculated positions */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- GtkWidget *widget;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- if (gtk_tool_item_group_get_n_items (group->widget))
- {
- gint size = group_sizes[i];
-
- if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget))
- {
- size += MIN (expand_space, remaining_space);
- remaining_space -= expand_space;
- }
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.height = size;
- else
- child_allocation.width = size;
-
- if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
- GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - x - child_allocation.width;
- else
- child_allocation.x = x;
-
- gtk_widget_size_allocate (widget, &child_allocation);
- gtk_widget_show (widget);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.y += child_allocation.height;
- else
- x += child_allocation.width;
- }
- else
- gtk_widget_hide (widget);
- }
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- child_allocation.y += border_width;
- child_allocation.y += offset;
-
- page_start = child_allocation.y;
- }
- else
- {
- x += border_width;
- x += offset;
-
- page_start = x;
- }
-
- /* update the scrollbar to match the displayed adjustment */
- if (adjustment)
- {
- gdouble value;
-
- adjustment->page_increment = page_size * 0.9;
- adjustment->step_increment = page_size * 0.1;
- adjustment->page_size = page_size;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation ||
- GTK_TEXT_DIR_LTR == direction)
- {
- adjustment->lower = 0;
- adjustment->upper = MAX (0, page_start);
-
- value = MIN (offset, adjustment->upper - adjustment->page_size);
- gtk_adjustment_clamp_page (adjustment, value, offset + page_size);
- }
- else
- {
- adjustment->lower = page_size - MAX (0, page_start);
- adjustment->upper = page_size;
-
- offset = -offset;
-
- value = MAX (offset, adjustment->lower);
- gtk_adjustment_clamp_page (adjustment, offset, value + page_size);
- }
-
- gtk_adjustment_changed (adjustment);
- }
-}
-
-static gboolean
-gtk_tool_palette_expose_event (GtkWidget *widget,
- GdkEventExpose *event)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GdkDisplay *display;
- cairo_t *cr;
- guint i;
-
- display = gdk_drawable_get_display (widget->window);
-
- if (!gdk_display_supports_composite (display))
- return FALSE;
-
- cr = gdk_cairo_create (widget->window);
- gdk_cairo_region (cr, event->region);
- cairo_clip (cr);
-
- cairo_push_group (cr);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if (palette->priv->groups[i].widget)
- _gtk_tool_item_group_paint (palette->priv->groups[i].widget, cr);
-
- cairo_pop_group_to_source (cr);
-
- cairo_paint (cr);
- cairo_destroy (cr);
-
- return FALSE;
-}
-
-static void
-gtk_tool_palette_realize (GtkWidget *widget)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- GdkWindowAttr attributes;
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - border_width * 2;
- attributes.height = widget->allocation.height - border_width * 2;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
-
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_set_parent_window,
- widget->window);
-
- gtk_widget_queue_resize_no_redraw (widget);
-}
-
-static void
-gtk_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED,
- gpointer data)
-{
- GtkWidget *widget = GTK_WIDGET (data);
- gtk_tool_palette_size_allocate (widget, &widget->allocation);
-}
-
-static void
-gtk_tool_palette_set_scroll_adjustments (GtkWidget *widget,
- GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
-
- if (palette->priv->hadjustment)
- g_object_unref (palette->priv->hadjustment);
- if (palette->priv->vadjustment)
- g_object_unref (palette->priv->vadjustment);
-
- if (hadjustment)
- g_object_ref_sink (hadjustment);
- if (vadjustment)
- g_object_ref_sink (vadjustment);
-
- palette->priv->hadjustment = hadjustment;
- palette->priv->vadjustment = vadjustment;
-
- if (palette->priv->hadjustment)
- g_signal_connect (palette->priv->hadjustment, "value-changed",
- G_CALLBACK (gtk_tool_palette_adjustment_value_changed),
- palette);
- if (palette->priv->vadjustment)
- g_signal_connect (palette->priv->vadjustment, "value-changed",
- G_CALLBACK (gtk_tool_palette_adjustment_value_changed),
- palette);
-}
-
-static void
-gtk_tool_palette_repack (GtkToolPalette *palette)
-{
- guint si, di;
-
- for (si = di = 0; di < palette->priv->groups_length; ++si)
- {
- if (palette->priv->groups[si].widget)
- {
- palette->priv->groups[di] = palette->priv->groups[si];
- ++di;
- }
- else
- --palette->priv->groups_length;
- }
-
- palette->priv->sparse_groups = FALSE;
-}
-
-static void
-gtk_tool_palette_add (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolPalette *palette;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (child));
-
- palette = GTK_TOOL_PALETTE (container);
-
- if (palette->priv->groups_length == palette->priv->groups_size)
- gtk_tool_palette_repack (palette);
-
- if (palette->priv->groups_length == palette->priv->groups_size)
- {
- gsize old_size = palette->priv->groups_size;
- gsize new_size = old_size * 2;
-
- palette->priv->groups = g_renew (GtkToolItemGroupInfo,
- palette->priv->groups,
- new_size);
-
- memset (palette->priv->groups + old_size, 0,
- sizeof (GtkToolItemGroupInfo) * old_size);
-
- palette->priv->groups_size = new_size;
- }
-
- palette->priv->groups[palette->priv->groups_length].widget = g_object_ref_sink (child);
- palette->priv->groups_length += 1;
-
- gtk_widget_set_parent (child, GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolPalette *palette;
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (container));
- palette = GTK_TOOL_PALETTE (container);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if ((GtkWidget*) palette->priv->groups[i].widget == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- memset (&palette->priv->groups[i], 0, sizeof (GtkToolItemGroupInfo));
- palette->priv->sparse_groups = TRUE;
- }
-}
-
-static void
-gtk_tool_palette_forall (GtkContainer *container,
- gboolean internals G_GNUC_UNUSED,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
- guint i;
-
- if (palette->priv->groups)
- {
- for (i = 0; i < palette->priv->groups_length; ++i)
- if (palette->priv->groups[i].widget)
- callback (GTK_WIDGET (palette->priv->groups[i].widget),
- callback_data);
- }
-}
-
-static GType
-gtk_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED)
-{
- return GTK_TYPE_TOOL_ITEM_GROUP;
-}
-
-static void
-gtk_tool_palette_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
-
- switch (prop_id)
- {
- case CHILD_PROP_EXCLUSIVE:
- gtk_tool_palette_set_exclusive (palette, child, g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_palette_set_expand (palette, child, g_value_get_boolean (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
-
- switch (prop_id)
- {
- case CHILD_PROP_EXCLUSIVE:
- g_value_set_boolean (value, gtk_tool_palette_get_exclusive (palette, child));
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, gtk_tool_palette_get_expand (palette, child));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_class_init (GtkToolPaletteClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_palette_set_property;
- oclass->get_property = gtk_tool_palette_get_property;
- oclass->dispose = gtk_tool_palette_dispose;
- oclass->finalize = gtk_tool_palette_finalize;
-
- wclass->size_request = gtk_tool_palette_size_request;
- wclass->size_allocate = gtk_tool_palette_size_allocate;
- wclass->expose_event = gtk_tool_palette_expose_event;
- wclass->realize = gtk_tool_palette_realize;
-
- cclass->add = gtk_tool_palette_add;
- cclass->remove = gtk_tool_palette_remove;
- cclass->forall = gtk_tool_palette_forall;
- cclass->child_type = gtk_tool_palette_child_type;
- cclass->set_child_property = gtk_tool_palette_set_child_property;
- cclass->get_child_property = gtk_tool_palette_get_child_property;
-
- cls->set_scroll_adjustments = gtk_tool_palette_set_scroll_adjustments;
- /**
- * GtkToolPalette::set-scroll-adjustments:
- * @widget: the GtkToolPalette that received the signal
- * @hadjustment: The horizontal adjustment
- * @vadjustment: The vertical adjustment
- *
- * The ::set-scroll-adjustments when FIXME
- *
- * Since: 2.18
- */
- wclass->set_scroll_adjustments_signal =
- g_signal_new ("set-scroll-adjustments",
- G_TYPE_FROM_CLASS (oclass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkToolPaletteClass, set_scroll_adjustments),
- NULL, NULL,
- _gtk_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2,
- GTK_TYPE_ADJUSTMENT,
- GTK_TYPE_ADJUSTMENT);
-
- g_object_class_install_property (oclass, PROP_ICON_SIZE,
- g_param_spec_enum ("icon-size",
- P_("Icon Size"),
- P_("The size of palette icons"),
- GTK_TYPE_ICON_SIZE,
- DEFAULT_ICON_SIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ORIENTATION,
- g_param_spec_enum ("orientation",
- P_("Orientation"),
- P_("Orientation of the tool palette"),
- GTK_TYPE_ORIENTATION,
- DEFAULT_ORIENTATION,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_TOOLBAR_STYLE,
- g_param_spec_enum ("toolbar-style",
- P_("Toolbar Style"),
- P_("Style of items in the tool palette"),
- GTK_TYPE_TOOLBAR_STYLE,
- DEFAULT_TOOLBAR_STYLE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXCLUSIVE,
- g_param_spec_boolean ("exclusive",
- P_("Exclusive"),
- P_("Whether the item group should be the only expanded at a given time"),
- DEFAULT_CHILD_EXCLUSIVE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item group should receive extra space when the palette grows"),
- DEFAULT_CHILD_EXPAND,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_type_class_add_private (cls, sizeof (GtkToolPalettePrivate));
-
- dnd_target_atom_item = gdk_atom_intern_static_string (dnd_targets[0].target);
- dnd_target_atom_group = gdk_atom_intern_static_string (dnd_targets[1].target);
-}
-
-/**
- * gtk_tool_palette_new:
- *
- * Creates a new tool palette.
- *
- * Returns: a new #GtkToolPalette.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_new (void)
-{
- return g_object_new (GTK_TYPE_TOOL_PALETTE, NULL);
-}
-
-/**
- * gtk_tool_palette_set_icon_size:
- * @palette: an #GtkToolPalette.
- * @icon_size: the #GtkIconSize that icons in the tool palette shall have.
- *
- * Sets the size of icons in the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_icon_size (GtkToolPalette *palette,
- GtkIconSize icon_size)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (icon_size != palette->priv->icon_size)
- g_object_set (palette, "icon-size", icon_size, NULL);
-}
-
-/**
- * gtk_tool_palette_set_orientation:
- * @palette: an #GtkToolPalette.
- * @orientation: the #GtkOrientation that the tool palette shall have.
- *
- * Sets the orientation (horizontal or vertical) of the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_orientation (GtkToolPalette *palette,
- GtkOrientation orientation)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (orientation != palette->priv->orientation)
- g_object_set (palette, "orientation", orientation, NULL);
-}
-
-/**
- * gtk_tool_palette_set_style:
- * @palette: an #GtkToolPalette.
- * @style: the #GtkToolbarStyle that items in the tool palette shall have.
- *
- * Sets the style (text, icons or both) of items in the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_style (GtkToolPalette *palette,
- GtkToolbarStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (style != palette->priv->style)
- g_object_set (palette, "toolbar-style", style, NULL);
-}
-
-/**
- * gtk_tool_palette_get_icon_size:
- * @palette: an #GtkToolPalette.
- *
- * Gets the size of icons in the tool palette. See gtk_tool_palette_set_icon_size().
- *
- * Returns: the #GtkIconSize of icons in the tool palette.
- *
- * Since: 2.18
- */
-GtkIconSize
-gtk_tool_palette_get_icon_size (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE);
- return palette->priv->icon_size;
-}
-
-/**
- * gtk_tool_palette_get_orientation:
- * @palette: an #GtkToolPalette.
- *
- * Gets the orientation (horizontal or vertical) of the tool palette. See gtk_tool_palette_set_orientation().
- *
- * Returns the #GtkOrientation of the tool palette.
- */
-GtkOrientation
-gtk_tool_palette_get_orientation (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION);
- return palette->priv->orientation;
-}
-
-/**
- * gtk_tool_palette_get_style:
- * @palette: an #GtkToolPalette.
- *
- * Gets the style (icons, text or both) of items in the tool palette.
- *
- * Returns: the #GtkToolbarStyle of items in the tool palette.
- *
- * Since: 2.18
- */
-GtkToolbarStyle
-gtk_tool_palette_get_style (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_TOOLBAR_STYLE);
- return palette->priv->style;
-}
-
-/**
- * gtk_tool_palette_set_group_position:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @position: a new index for group.
- *
- * Sets the position of the group as an index of the tool palette.
- * If position is 0 the group will become the first child, if position is
- * -1 it will become the last child.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_group_position (GtkToolPalette *palette,
- GtkWidget *group,
- gint position)
-{
- GtkToolItemGroupInfo group_info;
- gint old_position;
- gpointer src, dst;
- gsize len;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- gtk_tool_palette_repack (palette);
-
- g_return_if_fail (position >= -1);
-
- if (-1 == position)
- position = palette->priv->groups_length - 1;
-
- g_return_if_fail ((guint) position < palette->priv->groups_length);
-
- if (GTK_TOOL_ITEM_GROUP (group) == palette->priv->groups[position].widget)
- return;
-
- old_position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (old_position >= 0);
-
- group_info = palette->priv->groups[old_position];
-
- if (position < old_position)
- {
- dst = palette->priv->groups + position + 1;
- src = palette->priv->groups + position;
- len = old_position - position;
- }
- else
- {
- dst = palette->priv->groups + old_position;
- src = palette->priv->groups + old_position + 1;
- len = position - old_position;
- }
-
- memmove (dst, src, len * sizeof (*palette->priv->groups));
- palette->priv->groups[position] = group_info;
-
- gtk_widget_queue_resize (GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_group_notify_collapsed (GtkToolItemGroup *group,
- GParamSpec *pspec G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (data);
- guint i;
-
- if (gtk_tool_item_group_get_collapsed (group))
- return;
-
- for (i = 0; i < palette->priv->groups_size; ++i)
- {
- GtkToolItemGroup *current_group = palette->priv->groups[i].widget;
-
- if (current_group && current_group != group)
- gtk_tool_item_group_set_collapsed (palette->priv->groups[i].widget, TRUE);
- }
-}
-
-/**
- * gtk_tool_palette_set_exclusive:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @exclusive: whether the group should be exclusive or not.
- *
- * Sets whether the group should be exclusive or not. If an exclusive group is expanded
- * all other groups are collapsed.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_exclusive (GtkToolPalette *palette,
- GtkWidget *group,
- gboolean exclusive)
-{
- GtkToolItemGroupInfo *group_info;
- gint position;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (position >= 0);
-
- group_info = &palette->priv->groups[position];
-
- if (exclusive == group_info->exclusive)
- return;
-
- group_info->exclusive = exclusive;
-
- if (group_info->exclusive != (0 != group_info->notify_collapsed))
- {
- if (group_info->exclusive)
- {
- group_info->notify_collapsed =
- g_signal_connect (group, "notify::collapsed",
- G_CALLBACK (gtk_tool_palette_group_notify_collapsed),
- palette);
- }
- else
- {
- g_signal_handler_disconnect (group, group_info->notify_collapsed);
- group_info->notify_collapsed = 0;
- }
- }
-
- gtk_tool_palette_group_notify_collapsed (group_info->widget, NULL, palette);
- gtk_widget_child_notify (group, "exclusive");
-}
-
-/**
- * gtk_tool_palette_set_expand:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @expand: whether the group should be given extra space.
- *
- * Sets whether the group should be given extra space.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_expand (GtkToolPalette *palette,
- GtkWidget *group,
- gboolean expand)
-{
- GtkToolItemGroupInfo *group_info;
- gint position;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (position >= 0);
-
- group_info = &palette->priv->groups[position];
-
- if (expand != group_info->expand)
- {
- group_info->expand = expand;
- gtk_widget_queue_resize (GTK_WIDGET (palette));
- gtk_widget_child_notify (group, "expand");
- }
-}
-
-/**
- * gtk_tool_palette_get_group_position:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup.
- *
- * Gets the position of @group in @palette as index. see gtk_tool_palette_set_group_position().
- *
- * Returns: the index of group or -1 if @group is not a child of @palette.
- *
- * Since: 2.18
- */
-gint
-gtk_tool_palette_get_group_position (GtkToolPalette *palette,
- GtkWidget *group)
-{
- guint i;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if ((gpointer) group == palette->priv->groups[i].widget)
- return i;
-
- return -1;
-}
-
-/**
- * gtk_tool_palette_get_exclusive:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- *
- * Gets whether group is exclusive or not. See gtk_tool_palette_set_exclusive().
- *
- * Returns: %TRUE if group is exclusive.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_palette_get_exclusive (GtkToolPalette *palette,
- GtkWidget *group)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXCLUSIVE);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXCLUSIVE);
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXCLUSIVE);
-
- return palette->priv->groups[position].exclusive;
-}
-
-/**
- * gtk_tool_palette_get_expand:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- *
- * Gets whether group should be given extra space. See gtk_tool_palette_set_expand().
- *
- * Returns: %TRUE if group should be given extra space, %FALSE otherwise.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_palette_get_expand (GtkToolPalette *palette,
- GtkWidget *group)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXPAND);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXPAND);
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXPAND);
-
- return palette->priv->groups[position].expand;
-}
-
-/**
- * gtk_tool_palette_get_drop_item:
- * @palette: an #GtkToolPalette.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the item at position (x, y). See gtk_tool_palette_get_drop_group().
- *
- * Returns: the #GtkToolItem at position or %NULL if there is no such item.
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_palette_get_drop_item (GtkToolPalette *palette,
- gint x,
- gint y)
-{
- GtkWidget *group = gtk_tool_palette_get_drop_group (palette, x, y);
-
- if (group)
- return gtk_tool_item_group_get_drop_item (GTK_TOOL_ITEM_GROUP (group),
- x - group->allocation.x,
- y - group->allocation.y);
-
- return NULL;
-}
-
-/**
- * gtk_tool_palette_get_drop_group:
- * @palette: an #GtkToolPalette.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the group at position (x, y).
- *
- * Returns: the #GtkToolItemGroup at position or %NULL if there is no such group.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_get_drop_group (GtkToolPalette *palette,
- gint x,
- gint y)
-{
- GtkAllocation *allocation;
- guint i;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
-
- allocation = >K_WIDGET (palette)->allocation;
-
- g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation->height, NULL);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- GtkWidget *widget;
- gint x0, y0;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- x0 = x - widget->allocation.x;
- y0 = y - widget->allocation.y;
-
- if (x0 >= 0 && x0 < widget->allocation.width &&
- y0 >= 0 && y0 < widget->allocation.height)
- return widget;
- }
-
- return NULL;
-}
-
-/**
- * gtk_tool_palette_get_drag_item:
- * @palette: an #GtkToolPalette.
- * @selection: a #GtkSelectionData.
- *
- * Get the dragged item from the selection. This could be a #GtkToolItem or
- * an #GtkToolItemGroup.
- *
- * Returns: the dragged item in selection.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_get_drag_item (GtkToolPalette *palette,
- const GtkSelectionData *selection)
-{
- GtkToolPaletteDragData *data;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- g_return_val_if_fail (NULL != selection, NULL);
-
- g_return_val_if_fail (selection->format == 8, NULL);
- g_return_val_if_fail (selection->length == sizeof (GtkToolPaletteDragData), NULL);
- g_return_val_if_fail (selection->target == dnd_target_atom_item ||
- selection->target == dnd_target_atom_group,
- NULL);
-
- data = (GtkToolPaletteDragData*) selection->data;
-
- g_return_val_if_fail (data->palette == palette, NULL);
-
- if (dnd_target_atom_item == selection->target)
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (data->item), NULL);
- else if (dnd_target_atom_group == selection->target)
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (data->item), NULL);
-
- return data->item;
-}
-
-/**
- * gtk_tool_palette_set_drag_source:
- * @palette: an #GtkToolPalette.
- * @targets: the #GtkToolPaletteDragTargets which the widget should support.
- *
- * Sets the tool palette as a drag source. Enables all groups and items in
- * the tool palette as drag sources on button 1 and button 3 press with copy
- * and move actions.
- *
- * See gtk_drag_source_set().
- *
- * Since: 2.18
- *
- */
-void
-gtk_tool_palette_set_drag_source (GtkToolPalette *palette,
- GtkToolPaletteDragTargets targets)
-{
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if ((palette->priv->drag_source & targets) == targets)
- return;
-
- palette->priv->drag_source |= targets;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- if (palette->priv->groups[i].widget)
- gtk_container_forall (GTK_CONTAINER (palette->priv->groups[i].widget),
- _gtk_tool_palette_child_set_drag_source,
- palette);
- }
-}
-
-/**
- * gtk_tool_palette_add_drag_dest:
- * @palette: an #GtkToolPalette.
- * @widget: a #GtkWidget which should be a drag destination for palette.
- * @flags: the flags that specify what actions GTK+ should take for drops on that widget.
- * @targets: the #GtkToolPaletteDragTargets which the widget should support.
- * @actions: the #GdkDragAction<!-- -->s which the widget should suppport.
- *
- * Sets the tool palette as drag source (see gtk_tool_palette_set_drag_source) and
- * sets widget as a drag destination for drags from palette. With flags the actions
- * (like highlighting and target checking) which should be performed by GTK+ for
- * drops on widget can be specified. With targets the supported drag targets
- * (groups and/or items) can be specified. With actions the supported drag actions
- * (copy and move) can be specified.
- *
- * See gtk_drag_dest_set().
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_add_drag_dest (GtkToolPalette *palette,
- GtkWidget *widget,
- GtkDestDefaults flags,
- GtkToolPaletteDragTargets targets,
- GdkDragAction actions)
-{
- GtkTargetEntry entries[G_N_ELEMENTS (dnd_targets)];
- gint n_entries = 0;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- gtk_tool_palette_set_drag_source (palette,
- targets);
-
- if (targets & GTK_TOOL_PALETTE_DRAG_ITEMS)
- entries[n_entries++] = dnd_targets[0];
- if (targets & GTK_TOOL_PALETTE_DRAG_GROUPS)
- entries[n_entries++] = dnd_targets[1];
-
- gtk_drag_dest_set (widget, flags, entries, n_entries, actions);
-}
-
-void
-_gtk_tool_palette_get_item_size (GtkToolPalette *palette,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition max_requisition;
- gint max_rows;
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (NULL != item_size);
-
- max_requisition.width = 0;
- max_requisition.height = 0;
- max_rows = 0;
-
- /* iterate over all groups and calculate the max item_size and max row request */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkRequisition requisition;
- gint rows;
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (!group->widget)
- continue;
-
- _gtk_tool_item_group_item_size_request (group->widget, &requisition, homogeneous_only, &rows);
-
- max_requisition.width = MAX (max_requisition.width, requisition.width);
- max_requisition.height = MAX (max_requisition.height, requisition.height);
- max_rows = MAX (max_rows, rows);
- }
-
- *item_size = max_requisition;
- if (requested_rows)
- *requested_rows = max_rows;
-}
-
-static void
-gtk_tool_palette_item_drag_data_get (GtkWidget *widget,
- GdkDragContext *context G_GNUC_UNUSED,
- GtkSelectionData *selection,
- guint info G_GNUC_UNUSED,
- guint time G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL };
-
- if (selection->target == dnd_target_atom_item)
- drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM);
-
- if (drag_data.item)
- gtk_selection_data_set (selection, selection->target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
-}
-
-static void
-gtk_tool_palette_child_drag_data_get (GtkWidget *widget,
- GdkDragContext *context G_GNUC_UNUSED,
- GtkSelectionData *selection,
- guint info G_GNUC_UNUSED,
- guint time G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL };
-
- if (selection->target == dnd_target_atom_group)
- drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM_GROUP);
-
- if (drag_data.item)
- gtk_selection_data_set (selection, selection->target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
-}
-
-void
-_gtk_tool_palette_child_set_drag_source (GtkWidget *child,
- gpointer data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (data);
-
- /* Check drag_source,
- * to work properly when called from gtk_tool_item_group_insert().
- */
- if (!palette->priv->drag_source)
- return;
-
- if (GTK_IS_TOOL_ITEM (child) &&
- (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_ITEMS))
- {
- /* Connect to child instead of the item itself,
- * to work arround bug 510377.
- */
- if (GTK_IS_TOOL_BUTTON (child))
- child = gtk_bin_get_child (GTK_BIN (child));
-
- if (!child)
- return;
-
- gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
- &dnd_targets[0], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
- g_signal_connect (child, "drag-data-get",
- G_CALLBACK (gtk_tool_palette_item_drag_data_get),
- palette);
- }
- else if (GTK_IS_BUTTON (child) &&
- (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_GROUPS))
- {
- gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
- &dnd_targets[1], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
- g_signal_connect (child, "drag-data-get",
- G_CALLBACK (gtk_tool_palette_child_drag_data_get),
- palette);
- }
-}
-
-/**
- * gtk_tool_palette_get_drag_target_item:
- *
- * Get the target entry for a dragged #GtkToolItem.
- *
- * Returns: the #GtkTargetEntry for a dragged item.
- *
- * Since: 2.18
- */
-G_CONST_RETURN GtkTargetEntry*
-gtk_tool_palette_get_drag_target_item (void)
-{
- return &dnd_targets[0];
-}
-
-/**
- * gtk_tool_palette_get_drag_target_group:
- *
- * Get the target entry for a dragged #GtkToolItemGroup.
- *
- * Returns: the #GtkTargetEntry for a dragged group.
- *
- * Since: 2.18
- */
-G_CONST_RETURN GtkTargetEntry*
-gtk_tool_palette_get_drag_target_group (void)
-{
- return &dnd_targets[1];
-}
-
-void
-_gtk_tool_palette_set_expanding_child (GtkToolPalette *palette,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- palette->priv->expanding_child = widget;
-}
-
-GtkAdjustment*
-gtk_tool_palette_get_hadjustment (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- return palette->priv->hadjustment;
-}
-
-GtkAdjustment*
-gtk_tool_palette_get_vadjustment (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- return palette->priv->vadjustment;
-}
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
-
-GtkSizeGroup *
-_gtk_tool_palette_get_size_group (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
-
- return palette->priv->text_size_group;
-}
-
-#endif
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Mathias Hasselmann
- */
-
-#include "gtktoolpaletteprivate.h"
-#include "gtkmarshalers.h"
-
-#include <gtk/gtk.h>
-#include <string.h>
-
-#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR
-#define DEFAULT_ORIENTATION GTK_ORIENTATION_VERTICAL
-#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_ICONS
-
-#define DEFAULT_CHILD_EXCLUSIVE FALSE
-#define DEFAULT_CHILD_EXPAND FALSE
-
-#define P_(msgid) (msgid)
-
-/**
- * SECTION:GtkToolPalette
- * @short_description: A tool palette with categories
- * @include: gtktoolpalette.h
- *
- * An #GtkToolPalette allows it to add #GtkToolItem<!-- -->s to a palette like container
- * with different categories and drag and drop support.
- *
- * An #GtkToolPalette is created with a call to gtk_tool_palette_new().
- *
- * #GtkToolItem<!-- -->s cannot be added directly to an #GtkToolPalette, instead they
- * are added to an #GtkToolItemGroup which can than be added to an #GtkToolPalette. To add
- * an #GtkToolItemGroup to an #GtkToolPalette use gtk_container_add().
- *
- * |[
- * GtkWidget *palette, *group;
- * GtkToolItem *item;
- *
- * palette = gtk_tool_palette_new ();
- * group = gtk_tool_item_group_new (_("Test Category"));
- * gtk_container_add (GTK_CONTAINER (palette), group);
- *
- * item = gtk_tool_button_new_from_stock (GTK_STOCK_OK);
- * gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
- * ]|
- *
- * The easiest way to use drag and drop with GtkToolPalette is to call gtk_tool_palette_add_drag_dest()
- * with the desired drag source @palette and the desired drag target @widget. Than gtk_tool_palette_get_drag_item()
- * can be used to get the dragged item in the #GtkWidget::drag-data-received signal handler of the drag target.
- *
- * |[
- * static void
- * passive_canvas_drag_data_received (GtkWidget *widget,
- * GdkDragContext *context,
- * gint x,
- * gint y,
- * GtkSelectionData *selection,
- * guint info,
- * guint time,
- * gpointer data)
- * {
- * GtkWidget *palette;
- * GtkWidget *item;
- *
- * /<!-- -->* Get the dragged item *<!-- -->/
- * palette = gtk_widget_get_ancestor (gtk_drag_get_source_widget (context), GTK_TYPE_TOOL_PALETTE);
- * if (palette != NULL)
- * item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette), selection);
- *
- * /<!-- -->* Do something with item *<!-- -->/
- * }
- *
- * GtkWidget *target, palette;
- *
- * palette = gtk_tool_palette_new ();
- * target = gtk_drawing_area_new ();
- *
- * g_signal_connect (G_OBJECT (target), "drag-data-received",
- * G_CALLBACK (passive_canvas_drag_data_received), NULL);
- * gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette), target,
- * GTK_DEST_DEFAULT_ALL,
- * GTK_TOOL_PALETTE_DRAG_ITEMS,
- * GDK_ACTION_COPY);
- * ]|
- *
- * Since: 2.18
- */
-
-typedef struct _GtkToolItemGroupInfo GtkToolItemGroupInfo;
-typedef struct _GtkToolPaletteDragData GtkToolPaletteDragData;
-
-enum
-{
- PROP_NONE,
- PROP_ICON_SIZE,
- PROP_ORIENTATION,
- PROP_TOOLBAR_STYLE,
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_EXCLUSIVE,
- CHILD_PROP_EXPAND,
-};
-
-struct _GtkToolItemGroupInfo
-{
- GtkToolItemGroup *widget;
-
- guint notify_collapsed;
- guint exclusive : 1;
- guint expand : 1;
-};
-
-struct _GtkToolPalettePrivate
-{
- GtkToolItemGroupInfo *groups;
- gsize groups_size;
- gsize groups_length;
-
- GtkAdjustment *hadjustment;
- GtkAdjustment *vadjustment;
-
- GtkIconSize icon_size;
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- GtkWidget *expanding_child;
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- GtkSizeGroup *text_size_group;
-#endif
-
- guint sparse_groups : 1;
- guint drag_source : 2;
-};
-
-struct _GtkToolPaletteDragData
-{
- GtkToolPalette *palette;
- GtkWidget *item;
-};
-
-static GdkAtom dnd_target_atom_item = GDK_NONE;
-static GdkAtom dnd_target_atom_group = GDK_NONE;
-
-static const GtkTargetEntry dnd_targets[] =
-{
- { "application/x-GTK-tool-palette-item", GTK_TARGET_SAME_APP, 0 },
- { "application/x-GTK-tool-palette-group", GTK_TARGET_SAME_APP, 0 },
-};
-
-G_DEFINE_TYPE (GtkToolPalette,
- gtk_tool_palette,
- GTK_TYPE_CONTAINER);
-
-static void
-gtk_tool_palette_init (GtkToolPalette *palette)
-{
- palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette,
- GTK_TYPE_TOOL_PALETTE,
- GtkToolPalettePrivate);
-
- palette->priv->groups_size = 4;
- palette->priv->groups_length = 0;
- palette->priv->groups = g_new0 (GtkToolItemGroupInfo, palette->priv->groups_size);
-
- palette->priv->icon_size = DEFAULT_ICON_SIZE;
- palette->priv->orientation = DEFAULT_ORIENTATION;
- palette->priv->style = DEFAULT_TOOLBAR_STYLE;
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- palette->priv->text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
-#endif
-}
-
-static void
-gtk_tool_palette_reconfigured (GtkToolPalette *palette)
-{
- guint i;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- if (palette->priv->groups[i].widget)
- _gtk_tool_item_group_palette_reconfigured (palette->priv->groups[i].widget);
- }
-
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- switch (prop_id)
- {
- case PROP_ICON_SIZE:
- if ((guint) g_value_get_enum (value) != palette->priv->icon_size)
- {
- palette->priv->icon_size = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- case PROP_ORIENTATION:
- if ((guint) g_value_get_enum (value) != palette->priv->orientation)
- {
- palette->priv->orientation = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- case PROP_TOOLBAR_STYLE:
- if ((guint) g_value_get_enum (value) != palette->priv->style)
- {
- palette->priv->style = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- switch (prop_id)
- {
- case PROP_ICON_SIZE:
- g_value_set_enum (value, gtk_tool_palette_get_icon_size (palette));
- break;
-
- case PROP_ORIENTATION:
- g_value_set_enum (value, gtk_tool_palette_get_orientation (palette));
- break;
-
- case PROP_TOOLBAR_STYLE:
- g_value_set_enum (value, gtk_tool_palette_get_style (palette));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_dispose (GObject *object)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
- guint i;
-
- if (palette->priv->hadjustment)
- {
- g_object_unref (palette->priv->hadjustment);
- palette->priv->hadjustment = NULL;
- }
-
- if (palette->priv->vadjustment)
- {
- g_object_unref (palette->priv->vadjustment);
- palette->priv->vadjustment = NULL;
- }
-
- for (i = 0; i < palette->priv->groups_size; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (group->notify_collapsed)
- {
- g_signal_handler_disconnect (group->widget, group->notify_collapsed);
- group->notify_collapsed = 0;
- }
- }
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- if (palette->priv->text_size_group)
- {
- g_object_unref (palette->priv->text_size_group);
- palette->priv->text_size_group = NULL;
- }
-#endif
-
- G_OBJECT_CLASS (gtk_tool_palette_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_palette_finalize (GObject *object)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- if (palette->priv->groups)
- {
- palette->priv->groups_length = 0;
- g_free (palette->priv->groups);
- palette->priv->groups = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_palette_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_palette_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GtkRequisition child_requisition;
- guint i;
-
- requisition->width = 0;
- requisition->height = 0;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (!group->widget)
- continue;
-
- gtk_widget_size_request (GTK_WIDGET (group->widget), &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- requisition->width = MAX (requisition->width, child_requisition.width);
- requisition->height += child_requisition.height;
- }
- else
- {
- requisition->width += child_requisition.width;
- requisition->height = MAX (requisition->height, child_requisition.height);
- }
- }
-
- requisition->width += border_width * 2;
- requisition->height += border_width * 2;
-}
-
-static void
-gtk_tool_palette_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GtkAdjustment *adjustment = NULL;
- GtkAllocation child_allocation;
-
- gint n_expand_groups = 0;
- gint remaining_space = 0;
- gint expand_space = 0;
-
- gint page_start, page_size = 0;
- gint offset = 0;
- guint i;
-
- gint min_offset = -1, max_offset = -1;
-
- gint x;
-
- gint *group_sizes = g_newa(gint, palette->priv->groups_length);
-
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- GTK_WIDGET_CLASS (gtk_tool_palette_parent_class)->size_allocate (widget, allocation);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- adjustment = palette->priv->vadjustment;
- page_size = allocation->height;
- }
- else
- {
- adjustment = palette->priv->hadjustment;
- page_size = allocation->width;
- }
-
- if (adjustment)
- offset = gtk_adjustment_get_value (adjustment);
- if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
- GTK_TEXT_DIR_RTL == direction)
- offset = -offset;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.width = allocation->width - border_width * 2;
- else
- child_allocation.height = allocation->height - border_width * 2;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- remaining_space = allocation->height;
- else
- remaining_space = allocation->width;
-
- /* figure out the required size of all groups to be able to distribute the
- * remaining space on allocation */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- gint size;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- if (gtk_tool_item_group_get_n_items (group->widget))
- {
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- size = _gtk_tool_item_group_get_height_for_width (group->widget, child_allocation.width);
- else
- size = _gtk_tool_item_group_get_width_for_height (group->widget, child_allocation.height);
-
- if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget))
- n_expand_groups += 1;
- }
- else
- size = 0;
-
- remaining_space -= size;
- group_sizes[i] = size;
-
- /* if the widget is currently expanding an offset which allows to display as much of the
- * widget as possible is calculated */
- if (widget == palette->priv->expanding_child)
- {
- gint limit =
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
- child_allocation.width : child_allocation.height;
-
- gint real_size;
- guint j;
-
- min_offset = 0;
-
- for (j = 0; j < i; ++j)
- min_offset += group_sizes[j];
-
- max_offset = min_offset + group_sizes[i];
-
- real_size = _gtk_tool_item_group_get_size_for_limit
- (GTK_TOOL_ITEM_GROUP (widget), limit,
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation,
- FALSE);
-
- if (size == real_size)
- palette->priv->expanding_child = NULL;
- }
- }
-
- if (n_expand_groups > 0)
- {
- remaining_space = MAX (0, remaining_space);
- expand_space = remaining_space / n_expand_groups;
- }
-
- if (max_offset != -1)
- {
- gint limit =
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
- allocation->height : allocation->width;
-
- offset = MIN (MAX (offset, max_offset - limit), min_offset);
- }
-
- if (remaining_space > 0)
- offset = 0;
-
- x = border_width;
- child_allocation.y = border_width;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.y -= offset;
- else
- x -= offset;
-
- /* allocate all groups at the calculated positions */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- GtkWidget *widget;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- if (gtk_tool_item_group_get_n_items (group->widget))
- {
- gint size = group_sizes[i];
-
- if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget))
- {
- size += MIN (expand_space, remaining_space);
- remaining_space -= expand_space;
- }
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.height = size;
- else
- child_allocation.width = size;
-
- if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
- GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - x - child_allocation.width;
- else
- child_allocation.x = x;
-
- gtk_widget_size_allocate (widget, &child_allocation);
- gtk_widget_show (widget);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.y += child_allocation.height;
- else
- x += child_allocation.width;
- }
- else
- gtk_widget_hide (widget);
- }
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- child_allocation.y += border_width;
- child_allocation.y += offset;
-
- page_start = child_allocation.y;
- }
- else
- {
- x += border_width;
- x += offset;
-
- page_start = x;
- }
-
- /* update the scrollbar to match the displayed adjustment */
- if (adjustment)
- {
- gdouble value;
-
- adjustment->page_increment = page_size * 0.9;
- adjustment->step_increment = page_size * 0.1;
- adjustment->page_size = page_size;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation ||
- GTK_TEXT_DIR_LTR == direction)
- {
- adjustment->lower = 0;
- adjustment->upper = MAX (0, page_start);
-
- value = MIN (offset, adjustment->upper - adjustment->page_size);
- gtk_adjustment_clamp_page (adjustment, value, offset + page_size);
- }
- else
- {
- adjustment->lower = page_size - MAX (0, page_start);
- adjustment->upper = page_size;
-
- offset = -offset;
-
- value = MAX (offset, adjustment->lower);
- gtk_adjustment_clamp_page (adjustment, offset, value + page_size);
- }
-
- gtk_adjustment_changed (adjustment);
- }
-}
-
-static gboolean
-gtk_tool_palette_expose_event (GtkWidget *widget,
- GdkEventExpose *event)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GdkDisplay *display;
- cairo_t *cr;
- guint i;
-
- display = gdk_drawable_get_display (widget->window);
-
- if (!gdk_display_supports_composite (display))
- return FALSE;
-
- cr = gdk_cairo_create (widget->window);
- gdk_cairo_region (cr, event->region);
- cairo_clip (cr);
-
- cairo_push_group (cr);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if (palette->priv->groups[i].widget)
- _gtk_tool_item_group_paint (palette->priv->groups[i].widget, cr);
-
- cairo_pop_group_to_source (cr);
-
- cairo_paint (cr);
- cairo_destroy (cr);
-
- return FALSE;
-}
-
-static void
-gtk_tool_palette_realize (GtkWidget *widget)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- GdkWindowAttr attributes;
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - border_width * 2;
- attributes.height = widget->allocation.height - border_width * 2;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
-
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_set_parent_window,
- widget->window);
-
- gtk_widget_queue_resize_no_redraw (widget);
-}
-
-static void
-gtk_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED,
- gpointer data)
-{
- GtkWidget *widget = GTK_WIDGET (data);
- gtk_tool_palette_size_allocate (widget, &widget->allocation);
-}
-
-static void
-gtk_tool_palette_set_scroll_adjustments (GtkWidget *widget,
- GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
-
- if (palette->priv->hadjustment)
- g_object_unref (palette->priv->hadjustment);
- if (palette->priv->vadjustment)
- g_object_unref (palette->priv->vadjustment);
-
- if (hadjustment)
- g_object_ref_sink (hadjustment);
- if (vadjustment)
- g_object_ref_sink (vadjustment);
-
- palette->priv->hadjustment = hadjustment;
- palette->priv->vadjustment = vadjustment;
-
- if (palette->priv->hadjustment)
- g_signal_connect (palette->priv->hadjustment, "value-changed",
- G_CALLBACK (gtk_tool_palette_adjustment_value_changed),
- palette);
- if (palette->priv->vadjustment)
- g_signal_connect (palette->priv->vadjustment, "value-changed",
- G_CALLBACK (gtk_tool_palette_adjustment_value_changed),
- palette);
-}
-
-static void
-gtk_tool_palette_repack (GtkToolPalette *palette)
-{
- guint si, di;
-
- for (si = di = 0; di < palette->priv->groups_length; ++si)
- {
- if (palette->priv->groups[si].widget)
- {
- palette->priv->groups[di] = palette->priv->groups[si];
- ++di;
- }
- else
- --palette->priv->groups_length;
- }
-
- palette->priv->sparse_groups = FALSE;
-}
-
-static void
-gtk_tool_palette_add (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolPalette *palette;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (child));
-
- palette = GTK_TOOL_PALETTE (container);
-
- if (palette->priv->groups_length == palette->priv->groups_size)
- gtk_tool_palette_repack (palette);
-
- if (palette->priv->groups_length == palette->priv->groups_size)
- {
- gsize old_size = palette->priv->groups_size;
- gsize new_size = old_size * 2;
-
- palette->priv->groups = g_renew (GtkToolItemGroupInfo,
- palette->priv->groups,
- new_size);
-
- memset (palette->priv->groups + old_size, 0,
- sizeof (GtkToolItemGroupInfo) * old_size);
-
- palette->priv->groups_size = new_size;
- }
-
- palette->priv->groups[palette->priv->groups_length].widget = g_object_ref_sink (child);
- palette->priv->groups_length += 1;
-
- gtk_widget_set_parent (child, GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolPalette *palette;
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (container));
- palette = GTK_TOOL_PALETTE (container);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if ((GtkWidget*) palette->priv->groups[i].widget == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- memset (&palette->priv->groups[i], 0, sizeof (GtkToolItemGroupInfo));
- palette->priv->sparse_groups = TRUE;
- }
-}
-
-static void
-gtk_tool_palette_forall (GtkContainer *container,
- gboolean internals G_GNUC_UNUSED,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
- guint i;
-
- if (palette->priv->groups)
- {
- for (i = 0; i < palette->priv->groups_length; ++i)
- if (palette->priv->groups[i].widget)
- callback (GTK_WIDGET (palette->priv->groups[i].widget),
- callback_data);
- }
-}
-
-static GType
-gtk_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED)
-{
- return GTK_TYPE_TOOL_ITEM_GROUP;
-}
-
-static void
-gtk_tool_palette_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
-
- switch (prop_id)
- {
- case CHILD_PROP_EXCLUSIVE:
- gtk_tool_palette_set_exclusive (palette, child, g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_palette_set_expand (palette, child, g_value_get_boolean (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
-
- switch (prop_id)
- {
- case CHILD_PROP_EXCLUSIVE:
- g_value_set_boolean (value, gtk_tool_palette_get_exclusive (palette, child));
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, gtk_tool_palette_get_expand (palette, child));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_class_init (GtkToolPaletteClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_palette_set_property;
- oclass->get_property = gtk_tool_palette_get_property;
- oclass->dispose = gtk_tool_palette_dispose;
- oclass->finalize = gtk_tool_palette_finalize;
-
- wclass->size_request = gtk_tool_palette_size_request;
- wclass->size_allocate = gtk_tool_palette_size_allocate;
- wclass->expose_event = gtk_tool_palette_expose_event;
- wclass->realize = gtk_tool_palette_realize;
-
- cclass->add = gtk_tool_palette_add;
- cclass->remove = gtk_tool_palette_remove;
- cclass->forall = gtk_tool_palette_forall;
- cclass->child_type = gtk_tool_palette_child_type;
- cclass->set_child_property = gtk_tool_palette_set_child_property;
- cclass->get_child_property = gtk_tool_palette_get_child_property;
-
- cls->set_scroll_adjustments = gtk_tool_palette_set_scroll_adjustments;
- /**
- * GtkToolPalette::set-scroll-adjustments:
- * @widget: the GtkToolPalette that received the signal
- * @hadjustment: The horizontal adjustment
- * @vadjustment: The vertical adjustment
- *
- * The ::set-scroll-adjustments when FIXME
- *
- * Since: 2.18
- */
- wclass->set_scroll_adjustments_signal =
- g_signal_new ("set-scroll-adjustments",
- G_TYPE_FROM_CLASS (oclass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkToolPaletteClass, set_scroll_adjustments),
- NULL, NULL,
- _gtk_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2,
- GTK_TYPE_ADJUSTMENT,
- GTK_TYPE_ADJUSTMENT);
-
- g_object_class_install_property (oclass, PROP_ICON_SIZE,
- g_param_spec_enum ("icon-size",
- P_("Icon Size"),
- P_("The size of palette icons"),
- GTK_TYPE_ICON_SIZE,
- DEFAULT_ICON_SIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ORIENTATION,
- g_param_spec_enum ("orientation",
- P_("Orientation"),
- P_("Orientation of the tool palette"),
- GTK_TYPE_ORIENTATION,
- DEFAULT_ORIENTATION,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_TOOLBAR_STYLE,
- g_param_spec_enum ("toolbar-style",
- P_("Toolbar Style"),
- P_("Style of items in the tool palette"),
- GTK_TYPE_TOOLBAR_STYLE,
- DEFAULT_TOOLBAR_STYLE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXCLUSIVE,
- g_param_spec_boolean ("exclusive",
- P_("Exclusive"),
- P_("Whether the item group should be the only expanded at a given time"),
- DEFAULT_CHILD_EXCLUSIVE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item group should receive extra space when the palette grows"),
- DEFAULT_CHILD_EXPAND,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_type_class_add_private (cls, sizeof (GtkToolPalettePrivate));
-
- dnd_target_atom_item = gdk_atom_intern_static_string (dnd_targets[0].target);
- dnd_target_atom_group = gdk_atom_intern_static_string (dnd_targets[1].target);
-}
-
-/**
- * gtk_tool_palette_new:
- *
- * Creates a new tool palette.
- *
- * Returns: a new #GtkToolPalette.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_new (void)
-{
- return g_object_new (GTK_TYPE_TOOL_PALETTE, NULL);
-}
-
-/**
- * gtk_tool_palette_set_icon_size:
- * @palette: an #GtkToolPalette.
- * @icon_size: the #GtkIconSize that icons in the tool palette shall have.
- *
- * Sets the size of icons in the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_icon_size (GtkToolPalette *palette,
- GtkIconSize icon_size)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (icon_size != palette->priv->icon_size)
- g_object_set (palette, "icon-size", icon_size, NULL);
-}
-
-/**
- * gtk_tool_palette_set_orientation:
- * @palette: an #GtkToolPalette.
- * @orientation: the #GtkOrientation that the tool palette shall have.
- *
- * Sets the orientation (horizontal or vertical) of the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_orientation (GtkToolPalette *palette,
- GtkOrientation orientation)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (orientation != palette->priv->orientation)
- g_object_set (palette, "orientation", orientation, NULL);
-}
-
-/**
- * gtk_tool_palette_set_style:
- * @palette: an #GtkToolPalette.
- * @style: the #GtkToolbarStyle that items in the tool palette shall have.
- *
- * Sets the style (text, icons or both) of items in the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_style (GtkToolPalette *palette,
- GtkToolbarStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (style != palette->priv->style)
- g_object_set (palette, "toolbar-style", style, NULL);
-}
-
-/**
- * gtk_tool_palette_get_icon_size:
- * @palette: an #GtkToolPalette.
- *
- * Gets the size of icons in the tool palette. See gtk_tool_palette_set_icon_size().
- *
- * Returns: the #GtkIconSize of icons in the tool palette.
- *
- * Since: 2.18
- */
-GtkIconSize
-gtk_tool_palette_get_icon_size (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE);
- return palette->priv->icon_size;
-}
-
-/**
- * gtk_tool_palette_get_orientation:
- * @palette: an #GtkToolPalette.
- *
- * Gets the orientation (horizontal or vertical) of the tool palette. See gtk_tool_palette_set_orientation().
- *
- * Returns the #GtkOrientation of the tool palette.
- */
-GtkOrientation
-gtk_tool_palette_get_orientation (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION);
- return palette->priv->orientation;
-}
-
-/**
- * gtk_tool_palette_get_style:
- * @palette: an #GtkToolPalette.
- *
- * Gets the style (icons, text or both) of items in the tool palette.
- *
- * Returns: the #GtkToolbarStyle of items in the tool palette.
- *
- * Since: 2.18
- */
-GtkToolbarStyle
-gtk_tool_palette_get_style (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_TOOLBAR_STYLE);
- return palette->priv->style;
-}
-
-/**
- * gtk_tool_palette_set_group_position:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @position: a new index for group.
- *
- * Sets the position of the group as an index of the tool palette.
- * If position is 0 the group will become the first child, if position is
- * -1 it will become the last child.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_group_position (GtkToolPalette *palette,
- GtkWidget *group,
- gint position)
-{
- GtkToolItemGroupInfo group_info;
- gint old_position;
- gpointer src, dst;
- gsize len;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- gtk_tool_palette_repack (palette);
-
- g_return_if_fail (position >= -1);
-
- if (-1 == position)
- position = palette->priv->groups_length - 1;
-
- g_return_if_fail ((guint) position < palette->priv->groups_length);
-
- if (GTK_TOOL_ITEM_GROUP (group) == palette->priv->groups[position].widget)
- return;
-
- old_position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (old_position >= 0);
-
- group_info = palette->priv->groups[old_position];
-
- if (position < old_position)
- {
- dst = palette->priv->groups + position + 1;
- src = palette->priv->groups + position;
- len = old_position - position;
- }
- else
- {
- dst = palette->priv->groups + old_position;
- src = palette->priv->groups + old_position + 1;
- len = position - old_position;
- }
-
- memmove (dst, src, len * sizeof (*palette->priv->groups));
- palette->priv->groups[position] = group_info;
-
- gtk_widget_queue_resize (GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_group_notify_collapsed (GtkToolItemGroup *group,
- GParamSpec *pspec G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (data);
- guint i;
-
- if (gtk_tool_item_group_get_collapsed (group))
- return;
-
- for (i = 0; i < palette->priv->groups_size; ++i)
- {
- GtkToolItemGroup *current_group = palette->priv->groups[i].widget;
-
- if (current_group && current_group != group)
- gtk_tool_item_group_set_collapsed (palette->priv->groups[i].widget, TRUE);
- }
-}
-
-/**
- * gtk_tool_palette_set_exclusive:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @exclusive: whether the group should be exclusive or not.
- *
- * Sets whether the group should be exclusive or not. If an exclusive group is expanded
- * all other groups are collapsed.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_exclusive (GtkToolPalette *palette,
- GtkWidget *group,
- gboolean exclusive)
-{
- GtkToolItemGroupInfo *group_info;
- gint position;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (position >= 0);
-
- group_info = &palette->priv->groups[position];
-
- if (exclusive == group_info->exclusive)
- return;
-
- group_info->exclusive = exclusive;
-
- if (group_info->exclusive != (0 != group_info->notify_collapsed))
- {
- if (group_info->exclusive)
- {
- group_info->notify_collapsed =
- g_signal_connect (group, "notify::collapsed",
- G_CALLBACK (gtk_tool_palette_group_notify_collapsed),
- palette);
- }
- else
- {
- g_signal_handler_disconnect (group, group_info->notify_collapsed);
- group_info->notify_collapsed = 0;
- }
- }
-
- gtk_tool_palette_group_notify_collapsed (group_info->widget, NULL, palette);
- gtk_widget_child_notify (group, "exclusive");
-}
-
-/**
- * gtk_tool_palette_set_expand:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @expand: whether the group should be given extra space.
- *
- * Sets whether the group should be given extra space.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_expand (GtkToolPalette *palette,
- GtkWidget *group,
- gboolean expand)
-{
- GtkToolItemGroupInfo *group_info;
- gint position;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (position >= 0);
-
- group_info = &palette->priv->groups[position];
-
- if (expand != group_info->expand)
- {
- group_info->expand = expand;
- gtk_widget_queue_resize (GTK_WIDGET (palette));
- gtk_widget_child_notify (group, "expand");
- }
-}
-
-/**
- * gtk_tool_palette_get_group_position:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup.
- *
- * Gets the position of @group in @palette as index. see gtk_tool_palette_set_group_position().
- *
- * Returns: the index of group or -1 if @group is not a child of @palette.
- *
- * Since: 2.18
- */
-gint
-gtk_tool_palette_get_group_position (GtkToolPalette *palette,
- GtkWidget *group)
-{
- guint i;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if ((gpointer) group == palette->priv->groups[i].widget)
- return i;
-
- return -1;
-}
-
-/**
- * gtk_tool_palette_get_exclusive:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- *
- * Gets whether group is exclusive or not. See gtk_tool_palette_set_exclusive().
- *
- * Returns: %TRUE if group is exclusive.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_palette_get_exclusive (GtkToolPalette *palette,
- GtkWidget *group)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXCLUSIVE);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXCLUSIVE);
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXCLUSIVE);
-
- return palette->priv->groups[position].exclusive;
-}
-
-/**
- * gtk_tool_palette_get_expand:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- *
- * Gets whether group should be given extra space. See gtk_tool_palette_set_expand().
- *
- * Returns: %TRUE if group should be given extra space, %FALSE otherwise.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_palette_get_expand (GtkToolPalette *palette,
- GtkWidget *group)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXPAND);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXPAND);
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXPAND);
-
- return palette->priv->groups[position].expand;
-}
-
-/**
- * gtk_tool_palette_get_drop_item:
- * @palette: an #GtkToolPalette.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the item at position (x, y). See gtk_tool_palette_get_drop_group().
- *
- * Returns: the #GtkToolItem at position or %NULL if there is no such item.
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_palette_get_drop_item (GtkToolPalette *palette,
- gint x,
- gint y)
-{
- GtkWidget *group = gtk_tool_palette_get_drop_group (palette, x, y);
-
- if (group)
- return gtk_tool_item_group_get_drop_item (GTK_TOOL_ITEM_GROUP (group),
- x - group->allocation.x,
- y - group->allocation.y);
-
- return NULL;
-}
-
-/**
- * gtk_tool_palette_get_drop_group:
- * @palette: an #GtkToolPalette.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the group at position (x, y).
- *
- * Returns: the #GtkToolItemGroup at position or %NULL if there is no such group.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_get_drop_group (GtkToolPalette *palette,
- gint x,
- gint y)
-{
- GtkAllocation *allocation;
- guint i;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
-
- allocation = >K_WIDGET (palette)->allocation;
-
- g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation->height, NULL);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- GtkWidget *widget;
- gint x0, y0;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- x0 = x - widget->allocation.x;
- y0 = y - widget->allocation.y;
-
- if (x0 >= 0 && x0 < widget->allocation.width &&
- y0 >= 0 && y0 < widget->allocation.height)
- return widget;
- }
-
- return NULL;
-}
-
-/**
- * gtk_tool_palette_get_drag_item:
- * @palette: an #GtkToolPalette.
- * @selection: a #GtkSelectionData.
- *
- * Get the dragged item from the selection. This could be a #GtkToolItem or
- * an #GtkToolItemGroup.
- *
- * Returns: the dragged item in selection.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_get_drag_item (GtkToolPalette *palette,
- const GtkSelectionData *selection)
-{
- GtkToolPaletteDragData *data;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- g_return_val_if_fail (NULL != selection, NULL);
-
- g_return_val_if_fail (selection->format == 8, NULL);
- g_return_val_if_fail (selection->length == sizeof (GtkToolPaletteDragData), NULL);
- g_return_val_if_fail (selection->target == dnd_target_atom_item ||
- selection->target == dnd_target_atom_group,
- NULL);
-
- data = (GtkToolPaletteDragData*) selection->data;
-
- g_return_val_if_fail (data->palette == palette, NULL);
-
- if (dnd_target_atom_item == selection->target)
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (data->item), NULL);
- else if (dnd_target_atom_group == selection->target)
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (data->item), NULL);
-
- return data->item;
-}
-
-/**
- * gtk_tool_palette_set_drag_source:
- * @palette: an #GtkToolPalette.
- * @targets: the #GtkToolPaletteDragTargets which the widget should support.
- *
- * Sets the tool palette as a drag source. Enables all groups and items in
- * the tool palette as drag sources on button 1 and button 3 press with copy
- * and move actions.
- *
- * See gtk_drag_source_set().
- *
- * Since: 2.18
- *
- */
-void
-gtk_tool_palette_set_drag_source (GtkToolPalette *palette,
- GtkToolPaletteDragTargets targets)
-{
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if ((palette->priv->drag_source & targets) == targets)
- return;
-
- palette->priv->drag_source |= targets;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- if (palette->priv->groups[i].widget)
- gtk_container_forall (GTK_CONTAINER (palette->priv->groups[i].widget),
- _gtk_tool_palette_child_set_drag_source,
- palette);
- }
-}
-
-/**
- * gtk_tool_palette_add_drag_dest:
- * @palette: an #GtkToolPalette.
- * @widget: a #GtkWidget which should be a drag destination for palette.
- * @flags: the flags that specify what actions GTK+ should take for drops on that widget.
- * @targets: the #GtkToolPaletteDragTargets which the widget should support.
- * @actions: the #GdkDragAction<!-- -->s which the widget should suppport.
- *
- * Sets the tool palette as drag source (see gtk_tool_palette_set_drag_source) and
- * sets widget as a drag destination for drags from palette. With flags the actions
- * (like highlighting and target checking) which should be performed by GTK+ for
- * drops on widget can be specified. With targets the supported drag targets
- * (groups and/or items) can be specified. With actions the supported drag actions
- * (copy and move) can be specified.
- *
- * See gtk_drag_dest_set().
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_add_drag_dest (GtkToolPalette *palette,
- GtkWidget *widget,
- GtkDestDefaults flags,
- GtkToolPaletteDragTargets targets,
- GdkDragAction actions)
-{
- GtkTargetEntry entries[G_N_ELEMENTS (dnd_targets)];
- gint n_entries = 0;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- gtk_tool_palette_set_drag_source (palette,
- targets);
-
- if (targets & GTK_TOOL_PALETTE_DRAG_ITEMS)
- entries[n_entries++] = dnd_targets[0];
- if (targets & GTK_TOOL_PALETTE_DRAG_GROUPS)
- entries[n_entries++] = dnd_targets[1];
-
- gtk_drag_dest_set (widget, flags, entries, n_entries, actions);
-}
-
-void
-_gtk_tool_palette_get_item_size (GtkToolPalette *palette,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition max_requisition;
- gint max_rows;
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (NULL != item_size);
-
- max_requisition.width = 0;
- max_requisition.height = 0;
- max_rows = 0;
-
- /* iterate over all groups and calculate the max item_size and max row request */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkRequisition requisition;
- gint rows;
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (!group->widget)
- continue;
-
- _gtk_tool_item_group_item_size_request (group->widget, &requisition, homogeneous_only, &rows);
-
- max_requisition.width = MAX (max_requisition.width, requisition.width);
- max_requisition.height = MAX (max_requisition.height, requisition.height);
- max_rows = MAX (max_rows, rows);
- }
-
- *item_size = max_requisition;
- if (requested_rows)
- *requested_rows = max_rows;
-}
-
-static void
-gtk_tool_palette_item_drag_data_get (GtkWidget *widget,
- GdkDragContext *context G_GNUC_UNUSED,
- GtkSelectionData *selection,
- guint info G_GNUC_UNUSED,
- guint time G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL };
-
- if (selection->target == dnd_target_atom_item)
- drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM);
-
- if (drag_data.item)
- gtk_selection_data_set (selection, selection->target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
-}
-
-static void
-gtk_tool_palette_child_drag_data_get (GtkWidget *widget,
- GdkDragContext *context G_GNUC_UNUSED,
- GtkSelectionData *selection,
- guint info G_GNUC_UNUSED,
- guint time G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL };
-
- if (selection->target == dnd_target_atom_group)
- drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM_GROUP);
-
- if (drag_data.item)
- gtk_selection_data_set (selection, selection->target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
-}
-
-void
-_gtk_tool_palette_child_set_drag_source (GtkWidget *child,
- gpointer data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (data);
-
- /* Check drag_source,
- * to work properly when called from gtk_tool_item_group_insert().
- */
- if (!palette->priv->drag_source)
- return;
-
- if (GTK_IS_TOOL_ITEM (child) &&
- (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_ITEMS))
- {
- /* Connect to child instead of the item itself,
- * to work arround bug 510377.
- */
- if (GTK_IS_TOOL_BUTTON (child))
- child = gtk_bin_get_child (GTK_BIN (child));
-
- if (!child)
- return;
-
- gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
- &dnd_targets[0], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
- g_signal_connect (child, "drag-data-get",
- G_CALLBACK (gtk_tool_palette_item_drag_data_get),
- palette);
- }
- else if (GTK_IS_BUTTON (child) &&
- (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_GROUPS))
- {
- gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
- &dnd_targets[1], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
- g_signal_connect (child, "drag-data-get",
- G_CALLBACK (gtk_tool_palette_child_drag_data_get),
- palette);
- }
-}
-
-/**
- * gtk_tool_palette_get_drag_target_item:
- *
- * Get the target entry for a dragged #GtkToolItem.
- *
- * Returns: the #GtkTargetEntry for a dragged item.
- *
- * Since: 2.18
- */
-G_CONST_RETURN GtkTargetEntry*
-gtk_tool_palette_get_drag_target_item (void)
-{
- return &dnd_targets[0];
-}
-
-/**
- * gtk_tool_palette_get_drag_target_group:
- *
- * Get the target entry for a dragged #GtkToolItemGroup.
- *
- * Returns: the #GtkTargetEntry for a dragged group.
- *
- * Since: 2.18
- */
-G_CONST_RETURN GtkTargetEntry*
-gtk_tool_palette_get_drag_target_group (void)
-{
- return &dnd_targets[1];
-}
-
-void
-_gtk_tool_palette_set_expanding_child (GtkToolPalette *palette,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- palette->priv->expanding_child = widget;
-}
-
-GtkAdjustment*
-gtk_tool_palette_get_hadjustment (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- return palette->priv->hadjustment;
-}
-
-GtkAdjustment*
-gtk_tool_palette_get_vadjustment (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- return palette->priv->vadjustment;
-}
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
-
-GtkSizeGroup *
-_gtk_tool_palette_get_size_group (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
-
- return palette->priv->text_size_group;
-}
-
-#endif
-/* GtkToolPalette -- A tool palette with categories and DnD support
- * Copyright (C) 2008 Openismus GmbH
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Authors:
- * Mathias Hasselmann
- */
-
-#include "gtktoolpaletteprivate.h"
-#include "gtkmarshalers.h"
-
-#include <gtk/gtk.h>
-#include <string.h>
-
-#define DEFAULT_ICON_SIZE GTK_ICON_SIZE_SMALL_TOOLBAR
-#define DEFAULT_ORIENTATION GTK_ORIENTATION_VERTICAL
-#define DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_ICONS
-
-#define DEFAULT_CHILD_EXCLUSIVE FALSE
-#define DEFAULT_CHILD_EXPAND FALSE
-
-#define P_(msgid) (msgid)
-
-/**
- * SECTION:GtkToolPalette
- * @short_description: A tool palette with categories
- * @include: gtktoolpalette.h
- *
- * An #GtkToolPalette allows it to add #GtkToolItem<!-- -->s to a palette like container
- * with different categories and drag and drop support.
- *
- * An #GtkToolPalette is created with a call to gtk_tool_palette_new().
- *
- * #GtkToolItem<!-- -->s cannot be added directly to an #GtkToolPalette, instead they
- * are added to an #GtkToolItemGroup which can than be added to an #GtkToolPalette. To add
- * an #GtkToolItemGroup to an #GtkToolPalette use gtk_container_add().
- *
- * |[
- * GtkWidget *palette, *group;
- * GtkToolItem *item;
- *
- * palette = gtk_tool_palette_new ();
- * group = gtk_tool_item_group_new (_("Test Category"));
- * gtk_container_add (GTK_CONTAINER (palette), group);
- *
- * item = gtk_tool_button_new_from_stock (GTK_STOCK_OK);
- * gtk_tool_item_group_insert (GTK_TOOL_ITEM_GROUP (group), item, -1);
- * ]|
- *
- * The easiest way to use drag and drop with GtkToolPalette is to call gtk_tool_palette_add_drag_dest()
- * with the desired drag source @palette and the desired drag target @widget. Than gtk_tool_palette_get_drag_item()
- * can be used to get the dragged item in the #GtkWidget::drag-data-received signal handler of the drag target.
- *
- * |[
- * static void
- * passive_canvas_drag_data_received (GtkWidget *widget,
- * GdkDragContext *context,
- * gint x,
- * gint y,
- * GtkSelectionData *selection,
- * guint info,
- * guint time,
- * gpointer data)
- * {
- * GtkWidget *palette;
- * GtkWidget *item;
- *
- * /<!-- -->* Get the dragged item *<!-- -->/
- * palette = gtk_widget_get_ancestor (gtk_drag_get_source_widget (context), GTK_TYPE_TOOL_PALETTE);
- * if (palette != NULL)
- * item = gtk_tool_palette_get_drag_item (GTK_TOOL_PALETTE (palette), selection);
- *
- * /<!-- -->* Do something with item *<!-- -->/
- * }
- *
- * GtkWidget *target, palette;
- *
- * palette = gtk_tool_palette_new ();
- * target = gtk_drawing_area_new ();
- *
- * g_signal_connect (G_OBJECT (target), "drag-data-received",
- * G_CALLBACK (passive_canvas_drag_data_received), NULL);
- * gtk_tool_palette_add_drag_dest (GTK_TOOL_PALETTE (palette), target,
- * GTK_DEST_DEFAULT_ALL,
- * GTK_TOOL_PALETTE_DRAG_ITEMS,
- * GDK_ACTION_COPY);
- * ]|
- *
- * Since: 2.18
- */
-
-typedef struct _GtkToolItemGroupInfo GtkToolItemGroupInfo;
-typedef struct _GtkToolPaletteDragData GtkToolPaletteDragData;
-
-enum
-{
- PROP_NONE,
- PROP_ICON_SIZE,
- PROP_ORIENTATION,
- PROP_TOOLBAR_STYLE,
-};
-
-enum
-{
- CHILD_PROP_NONE,
- CHILD_PROP_EXCLUSIVE,
- CHILD_PROP_EXPAND,
-};
-
-struct _GtkToolItemGroupInfo
-{
- GtkToolItemGroup *widget;
-
- guint notify_collapsed;
- guint exclusive : 1;
- guint expand : 1;
-};
-
-struct _GtkToolPalettePrivate
-{
- GtkToolItemGroupInfo *groups;
- gsize groups_size;
- gsize groups_length;
-
- GtkAdjustment *hadjustment;
- GtkAdjustment *vadjustment;
-
- GtkIconSize icon_size;
- GtkOrientation orientation;
- GtkToolbarStyle style;
-
- GtkWidget *expanding_child;
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- GtkSizeGroup *text_size_group;
-#endif
-
- guint sparse_groups : 1;
- guint drag_source : 2;
-};
-
-struct _GtkToolPaletteDragData
-{
- GtkToolPalette *palette;
- GtkWidget *item;
-};
-
-static GdkAtom dnd_target_atom_item = GDK_NONE;
-static GdkAtom dnd_target_atom_group = GDK_NONE;
-
-static const GtkTargetEntry dnd_targets[] =
-{
- { "application/x-GTK-tool-palette-item", GTK_TARGET_SAME_APP, 0 },
- { "application/x-GTK-tool-palette-group", GTK_TARGET_SAME_APP, 0 },
-};
-
-G_DEFINE_TYPE (GtkToolPalette,
- gtk_tool_palette,
- GTK_TYPE_CONTAINER);
-
-static void
-gtk_tool_palette_init (GtkToolPalette *palette)
-{
- palette->priv = G_TYPE_INSTANCE_GET_PRIVATE (palette,
- GTK_TYPE_TOOL_PALETTE,
- GtkToolPalettePrivate);
-
- palette->priv->groups_size = 4;
- palette->priv->groups_length = 0;
- palette->priv->groups = g_new0 (GtkToolItemGroupInfo, palette->priv->groups_size);
-
- palette->priv->icon_size = DEFAULT_ICON_SIZE;
- palette->priv->orientation = DEFAULT_ORIENTATION;
- palette->priv->style = DEFAULT_TOOLBAR_STYLE;
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- palette->priv->text_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
-#endif
-}
-
-static void
-gtk_tool_palette_reconfigured (GtkToolPalette *palette)
-{
- guint i;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- if (palette->priv->groups[i].widget)
- _gtk_tool_item_group_palette_reconfigured (palette->priv->groups[i].widget);
- }
-
- gtk_widget_queue_resize_no_redraw (GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- switch (prop_id)
- {
- case PROP_ICON_SIZE:
- if ((guint) g_value_get_enum (value) != palette->priv->icon_size)
- {
- palette->priv->icon_size = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- case PROP_ORIENTATION:
- if ((guint) g_value_get_enum (value) != palette->priv->orientation)
- {
- palette->priv->orientation = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- case PROP_TOOLBAR_STYLE:
- if ((guint) g_value_get_enum (value) != palette->priv->style)
- {
- palette->priv->style = g_value_get_enum (value);
- gtk_tool_palette_reconfigured (palette);
- }
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- switch (prop_id)
- {
- case PROP_ICON_SIZE:
- g_value_set_enum (value, gtk_tool_palette_get_icon_size (palette));
- break;
-
- case PROP_ORIENTATION:
- g_value_set_enum (value, gtk_tool_palette_get_orientation (palette));
- break;
-
- case PROP_TOOLBAR_STYLE:
- g_value_set_enum (value, gtk_tool_palette_get_style (palette));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_dispose (GObject *object)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
- guint i;
-
- if (palette->priv->hadjustment)
- {
- g_object_unref (palette->priv->hadjustment);
- palette->priv->hadjustment = NULL;
- }
-
- if (palette->priv->vadjustment)
- {
- g_object_unref (palette->priv->vadjustment);
- palette->priv->vadjustment = NULL;
- }
-
- for (i = 0; i < palette->priv->groups_size; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (group->notify_collapsed)
- {
- g_signal_handler_disconnect (group->widget, group->notify_collapsed);
- group->notify_collapsed = 0;
- }
- }
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
- if (palette->priv->text_size_group)
- {
- g_object_unref (palette->priv->text_size_group);
- palette->priv->text_size_group = NULL;
- }
-#endif
-
- G_OBJECT_CLASS (gtk_tool_palette_parent_class)->dispose (object);
-}
-
-static void
-gtk_tool_palette_finalize (GObject *object)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (object);
-
- if (palette->priv->groups)
- {
- palette->priv->groups_length = 0;
- g_free (palette->priv->groups);
- palette->priv->groups = NULL;
- }
-
- G_OBJECT_CLASS (gtk_tool_palette_parent_class)->finalize (object);
-}
-
-static void
-gtk_tool_palette_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GtkRequisition child_requisition;
- guint i;
-
- requisition->width = 0;
- requisition->height = 0;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (!group->widget)
- continue;
-
- gtk_widget_size_request (GTK_WIDGET (group->widget), &child_requisition);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- requisition->width = MAX (requisition->width, child_requisition.width);
- requisition->height += child_requisition.height;
- }
- else
- {
- requisition->width += child_requisition.width;
- requisition->height = MAX (requisition->height, child_requisition.height);
- }
- }
-
- requisition->width += border_width * 2;
- requisition->height += border_width * 2;
-}
-
-static void
-gtk_tool_palette_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GtkAdjustment *adjustment = NULL;
- GtkAllocation child_allocation;
-
- gint n_expand_groups = 0;
- gint remaining_space = 0;
- gint expand_space = 0;
-
- gint page_start, page_size = 0;
- gint offset = 0;
- guint i;
-
- gint min_offset = -1, max_offset = -1;
-
- gint x;
-
- gint *group_sizes = g_newa(gint, palette->priv->groups_length);
-
- GtkTextDirection direction = gtk_widget_get_direction (widget);
-
- GTK_WIDGET_CLASS (gtk_tool_palette_parent_class)->size_allocate (widget, allocation);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- adjustment = palette->priv->vadjustment;
- page_size = allocation->height;
- }
- else
- {
- adjustment = palette->priv->hadjustment;
- page_size = allocation->width;
- }
-
- if (adjustment)
- offset = gtk_adjustment_get_value (adjustment);
- if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
- GTK_TEXT_DIR_RTL == direction)
- offset = -offset;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.width = allocation->width - border_width * 2;
- else
- child_allocation.height = allocation->height - border_width * 2;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- remaining_space = allocation->height;
- else
- remaining_space = allocation->width;
-
- /* figure out the required size of all groups to be able to distribute the
- * remaining space on allocation */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- gint size;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- if (gtk_tool_item_group_get_n_items (group->widget))
- {
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- size = _gtk_tool_item_group_get_height_for_width (group->widget, child_allocation.width);
- else
- size = _gtk_tool_item_group_get_width_for_height (group->widget, child_allocation.height);
-
- if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget))
- n_expand_groups += 1;
- }
- else
- size = 0;
-
- remaining_space -= size;
- group_sizes[i] = size;
-
- /* if the widget is currently expanding an offset which allows to display as much of the
- * widget as possible is calculated */
- if (widget == palette->priv->expanding_child)
- {
- gint limit =
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
- child_allocation.width : child_allocation.height;
-
- gint real_size;
- guint j;
-
- min_offset = 0;
-
- for (j = 0; j < i; ++j)
- min_offset += group_sizes[j];
-
- max_offset = min_offset + group_sizes[i];
-
- real_size = _gtk_tool_item_group_get_size_for_limit
- (GTK_TOOL_ITEM_GROUP (widget), limit,
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation,
- FALSE);
-
- if (size == real_size)
- palette->priv->expanding_child = NULL;
- }
- }
-
- if (n_expand_groups > 0)
- {
- remaining_space = MAX (0, remaining_space);
- expand_space = remaining_space / n_expand_groups;
- }
-
- if (max_offset != -1)
- {
- gint limit =
- GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
- allocation->height : allocation->width;
-
- offset = MIN (MAX (offset, max_offset - limit), min_offset);
- }
-
- if (remaining_space > 0)
- offset = 0;
-
- x = border_width;
- child_allocation.y = border_width;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.y -= offset;
- else
- x -= offset;
-
- /* allocate all groups at the calculated positions */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- GtkWidget *widget;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- if (gtk_tool_item_group_get_n_items (group->widget))
- {
- gint size = group_sizes[i];
-
- if (group->expand && !gtk_tool_item_group_get_collapsed (group->widget))
- {
- size += MIN (expand_space, remaining_space);
- remaining_space -= expand_space;
- }
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.height = size;
- else
- child_allocation.width = size;
-
- if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
- GTK_TEXT_DIR_RTL == direction)
- child_allocation.x = allocation->width - x - child_allocation.width;
- else
- child_allocation.x = x;
-
- gtk_widget_size_allocate (widget, &child_allocation);
- gtk_widget_show (widget);
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- child_allocation.y += child_allocation.height;
- else
- x += child_allocation.width;
- }
- else
- gtk_widget_hide (widget);
- }
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation)
- {
- child_allocation.y += border_width;
- child_allocation.y += offset;
-
- page_start = child_allocation.y;
- }
- else
- {
- x += border_width;
- x += offset;
-
- page_start = x;
- }
-
- /* update the scrollbar to match the displayed adjustment */
- if (adjustment)
- {
- gdouble value;
-
- adjustment->page_increment = page_size * 0.9;
- adjustment->step_increment = page_size * 0.1;
- adjustment->page_size = page_size;
-
- if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation ||
- GTK_TEXT_DIR_LTR == direction)
- {
- adjustment->lower = 0;
- adjustment->upper = MAX (0, page_start);
-
- value = MIN (offset, adjustment->upper - adjustment->page_size);
- gtk_adjustment_clamp_page (adjustment, value, offset + page_size);
- }
- else
- {
- adjustment->lower = page_size - MAX (0, page_start);
- adjustment->upper = page_size;
-
- offset = -offset;
-
- value = MAX (offset, adjustment->lower);
- gtk_adjustment_clamp_page (adjustment, offset, value + page_size);
- }
-
- gtk_adjustment_changed (adjustment);
- }
-}
-
-static gboolean
-gtk_tool_palette_expose_event (GtkWidget *widget,
- GdkEventExpose *event)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
- GdkDisplay *display;
- cairo_t *cr;
- guint i;
-
- display = gdk_drawable_get_display (widget->window);
-
- if (!gdk_display_supports_composite (display))
- return FALSE;
-
- cr = gdk_cairo_create (widget->window);
- gdk_cairo_region (cr, event->region);
- cairo_clip (cr);
-
- cairo_push_group (cr);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if (palette->priv->groups[i].widget)
- _gtk_tool_item_group_paint (palette->priv->groups[i].widget, cr);
-
- cairo_pop_group_to_source (cr);
-
- cairo_paint (cr);
- cairo_destroy (cr);
-
- return FALSE;
-}
-
-static void
-gtk_tool_palette_realize (GtkWidget *widget)
-{
- const gint border_width = GTK_CONTAINER (widget)->border_width;
- gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
- GdkWindowAttr attributes;
-
- attributes.window_type = GDK_WINDOW_CHILD;
- attributes.x = widget->allocation.x + border_width;
- attributes.y = widget->allocation.y + border_width;
- attributes.width = widget->allocation.width - border_width * 2;
- attributes.height = widget->allocation.height - border_width * 2;
- attributes.wclass = GDK_INPUT_OUTPUT;
- attributes.visual = gtk_widget_get_visual (widget);
- attributes.colormap = gtk_widget_get_colormap (widget);
- attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
- | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_BUTTON_MOTION_MASK;
-
- widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
- &attributes, attributes_mask);
-
- gdk_window_set_user_data (widget->window, widget);
- widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
-
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_set_parent_window,
- widget->window);
-
- gtk_widget_queue_resize_no_redraw (widget);
-}
-
-static void
-gtk_tool_palette_adjustment_value_changed (GtkAdjustment *adjustment G_GNUC_UNUSED,
- gpointer data)
-{
- GtkWidget *widget = GTK_WIDGET (data);
- gtk_tool_palette_size_allocate (widget, &widget->allocation);
-}
-
-static void
-gtk_tool_palette_set_scroll_adjustments (GtkWidget *widget,
- GtkAdjustment *hadjustment,
- GtkAdjustment *vadjustment)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (widget);
-
- if (palette->priv->hadjustment)
- g_object_unref (palette->priv->hadjustment);
- if (palette->priv->vadjustment)
- g_object_unref (palette->priv->vadjustment);
-
- if (hadjustment)
- g_object_ref_sink (hadjustment);
- if (vadjustment)
- g_object_ref_sink (vadjustment);
-
- palette->priv->hadjustment = hadjustment;
- palette->priv->vadjustment = vadjustment;
-
- if (palette->priv->hadjustment)
- g_signal_connect (palette->priv->hadjustment, "value-changed",
- G_CALLBACK (gtk_tool_palette_adjustment_value_changed),
- palette);
- if (palette->priv->vadjustment)
- g_signal_connect (palette->priv->vadjustment, "value-changed",
- G_CALLBACK (gtk_tool_palette_adjustment_value_changed),
- palette);
-}
-
-static void
-gtk_tool_palette_repack (GtkToolPalette *palette)
-{
- guint si, di;
-
- for (si = di = 0; di < palette->priv->groups_length; ++si)
- {
- if (palette->priv->groups[si].widget)
- {
- palette->priv->groups[di] = palette->priv->groups[si];
- ++di;
- }
- else
- --palette->priv->groups_length;
- }
-
- palette->priv->sparse_groups = FALSE;
-}
-
-static void
-gtk_tool_palette_add (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolPalette *palette;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (container));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (child));
-
- palette = GTK_TOOL_PALETTE (container);
-
- if (palette->priv->groups_length == palette->priv->groups_size)
- gtk_tool_palette_repack (palette);
-
- if (palette->priv->groups_length == palette->priv->groups_size)
- {
- gsize old_size = palette->priv->groups_size;
- gsize new_size = old_size * 2;
-
- palette->priv->groups = g_renew (GtkToolItemGroupInfo,
- palette->priv->groups,
- new_size);
-
- memset (palette->priv->groups + old_size, 0,
- sizeof (GtkToolItemGroupInfo) * old_size);
-
- palette->priv->groups_size = new_size;
- }
-
- palette->priv->groups[palette->priv->groups_length].widget = g_object_ref_sink (child);
- palette->priv->groups_length += 1;
-
- gtk_widget_set_parent (child, GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_remove (GtkContainer *container,
- GtkWidget *child)
-{
- GtkToolPalette *palette;
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (container));
- palette = GTK_TOOL_PALETTE (container);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if ((GtkWidget*) palette->priv->groups[i].widget == child)
- {
- g_object_unref (child);
- gtk_widget_unparent (child);
-
- memset (&palette->priv->groups[i], 0, sizeof (GtkToolItemGroupInfo));
- palette->priv->sparse_groups = TRUE;
- }
-}
-
-static void
-gtk_tool_palette_forall (GtkContainer *container,
- gboolean internals G_GNUC_UNUSED,
- GtkCallback callback,
- gpointer callback_data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
- guint i;
-
- if (palette->priv->groups)
- {
- for (i = 0; i < palette->priv->groups_length; ++i)
- if (palette->priv->groups[i].widget)
- callback (GTK_WIDGET (palette->priv->groups[i].widget),
- callback_data);
- }
-}
-
-static GType
-gtk_tool_palette_child_type (GtkContainer *container G_GNUC_UNUSED)
-{
- return GTK_TYPE_TOOL_ITEM_GROUP;
-}
-
-static void
-gtk_tool_palette_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
-
- switch (prop_id)
- {
- case CHILD_PROP_EXCLUSIVE:
- gtk_tool_palette_set_exclusive (palette, child, g_value_get_boolean (value));
- break;
-
- case CHILD_PROP_EXPAND:
- gtk_tool_palette_set_expand (palette, child, g_value_get_boolean (value));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (container);
-
- switch (prop_id)
- {
- case CHILD_PROP_EXCLUSIVE:
- g_value_set_boolean (value, gtk_tool_palette_get_exclusive (palette, child));
- break;
-
- case CHILD_PROP_EXPAND:
- g_value_set_boolean (value, gtk_tool_palette_get_expand (palette, child));
- break;
-
- default:
- GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, prop_id, pspec);
- break;
- }
-}
-
-static void
-gtk_tool_palette_class_init (GtkToolPaletteClass *cls)
-{
- GObjectClass *oclass = G_OBJECT_CLASS (cls);
- GtkWidgetClass *wclass = GTK_WIDGET_CLASS (cls);
- GtkContainerClass *cclass = GTK_CONTAINER_CLASS (cls);
-
- oclass->set_property = gtk_tool_palette_set_property;
- oclass->get_property = gtk_tool_palette_get_property;
- oclass->dispose = gtk_tool_palette_dispose;
- oclass->finalize = gtk_tool_palette_finalize;
-
- wclass->size_request = gtk_tool_palette_size_request;
- wclass->size_allocate = gtk_tool_palette_size_allocate;
- wclass->expose_event = gtk_tool_palette_expose_event;
- wclass->realize = gtk_tool_palette_realize;
-
- cclass->add = gtk_tool_palette_add;
- cclass->remove = gtk_tool_palette_remove;
- cclass->forall = gtk_tool_palette_forall;
- cclass->child_type = gtk_tool_palette_child_type;
- cclass->set_child_property = gtk_tool_palette_set_child_property;
- cclass->get_child_property = gtk_tool_palette_get_child_property;
-
- cls->set_scroll_adjustments = gtk_tool_palette_set_scroll_adjustments;
- /**
- * GtkToolPalette::set-scroll-adjustments:
- * @widget: the GtkToolPalette that received the signal
- * @hadjustment: The horizontal adjustment
- * @vadjustment: The vertical adjustment
- *
- * The ::set-scroll-adjustments when FIXME
- *
- * Since: 2.18
- */
- wclass->set_scroll_adjustments_signal =
- g_signal_new ("set-scroll-adjustments",
- G_TYPE_FROM_CLASS (oclass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkToolPaletteClass, set_scroll_adjustments),
- NULL, NULL,
- _gtk_marshal_VOID__OBJECT_OBJECT,
- G_TYPE_NONE, 2,
- GTK_TYPE_ADJUSTMENT,
- GTK_TYPE_ADJUSTMENT);
-
- g_object_class_install_property (oclass, PROP_ICON_SIZE,
- g_param_spec_enum ("icon-size",
- P_("Icon Size"),
- P_("The size of palette icons"),
- GTK_TYPE_ICON_SIZE,
- DEFAULT_ICON_SIZE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_ORIENTATION,
- g_param_spec_enum ("orientation",
- P_("Orientation"),
- P_("Orientation of the tool palette"),
- GTK_TYPE_ORIENTATION,
- DEFAULT_ORIENTATION,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_object_class_install_property (oclass, PROP_TOOLBAR_STYLE,
- g_param_spec_enum ("toolbar-style",
- P_("Toolbar Style"),
- P_("Style of items in the tool palette"),
- GTK_TYPE_TOOLBAR_STYLE,
- DEFAULT_TOOLBAR_STYLE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXCLUSIVE,
- g_param_spec_boolean ("exclusive",
- P_("Exclusive"),
- P_("Whether the item group should be the only expanded at a given time"),
- DEFAULT_CHILD_EXCLUSIVE,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- gtk_container_class_install_child_property (cclass, CHILD_PROP_EXPAND,
- g_param_spec_boolean ("expand",
- P_("Expand"),
- P_("Whether the item group should receive extra space when the palette grows"),
- DEFAULT_CHILD_EXPAND,
- G_PARAM_READWRITE | G_PARAM_STATIC_NAME |
- G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
-
- g_type_class_add_private (cls, sizeof (GtkToolPalettePrivate));
-
- dnd_target_atom_item = gdk_atom_intern_static_string (dnd_targets[0].target);
- dnd_target_atom_group = gdk_atom_intern_static_string (dnd_targets[1].target);
-}
-
-/**
- * gtk_tool_palette_new:
- *
- * Creates a new tool palette.
- *
- * Returns: a new #GtkToolPalette.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_new (void)
-{
- return g_object_new (GTK_TYPE_TOOL_PALETTE, NULL);
-}
-
-/**
- * gtk_tool_palette_set_icon_size:
- * @palette: an #GtkToolPalette.
- * @icon_size: the #GtkIconSize that icons in the tool palette shall have.
- *
- * Sets the size of icons in the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_icon_size (GtkToolPalette *palette,
- GtkIconSize icon_size)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (icon_size != palette->priv->icon_size)
- g_object_set (palette, "icon-size", icon_size, NULL);
-}
-
-/**
- * gtk_tool_palette_set_orientation:
- * @palette: an #GtkToolPalette.
- * @orientation: the #GtkOrientation that the tool palette shall have.
- *
- * Sets the orientation (horizontal or vertical) of the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_orientation (GtkToolPalette *palette,
- GtkOrientation orientation)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (orientation != palette->priv->orientation)
- g_object_set (palette, "orientation", orientation, NULL);
-}
-
-/**
- * gtk_tool_palette_set_style:
- * @palette: an #GtkToolPalette.
- * @style: the #GtkToolbarStyle that items in the tool palette shall have.
- *
- * Sets the style (text, icons or both) of items in the tool palette.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_style (GtkToolPalette *palette,
- GtkToolbarStyle style)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if (style != palette->priv->style)
- g_object_set (palette, "toolbar-style", style, NULL);
-}
-
-/**
- * gtk_tool_palette_get_icon_size:
- * @palette: an #GtkToolPalette.
- *
- * Gets the size of icons in the tool palette. See gtk_tool_palette_set_icon_size().
- *
- * Returns: the #GtkIconSize of icons in the tool palette.
- *
- * Since: 2.18
- */
-GtkIconSize
-gtk_tool_palette_get_icon_size (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ICON_SIZE);
- return palette->priv->icon_size;
-}
-
-/**
- * gtk_tool_palette_get_orientation:
- * @palette: an #GtkToolPalette.
- *
- * Gets the orientation (horizontal or vertical) of the tool palette. See gtk_tool_palette_set_orientation().
- *
- * Returns the #GtkOrientation of the tool palette.
- */
-GtkOrientation
-gtk_tool_palette_get_orientation (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_ORIENTATION);
- return palette->priv->orientation;
-}
-
-/**
- * gtk_tool_palette_get_style:
- * @palette: an #GtkToolPalette.
- *
- * Gets the style (icons, text or both) of items in the tool palette.
- *
- * Returns: the #GtkToolbarStyle of items in the tool palette.
- *
- * Since: 2.18
- */
-GtkToolbarStyle
-gtk_tool_palette_get_style (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_TOOLBAR_STYLE);
- return palette->priv->style;
-}
-
-/**
- * gtk_tool_palette_set_group_position:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @position: a new index for group.
- *
- * Sets the position of the group as an index of the tool palette.
- * If position is 0 the group will become the first child, if position is
- * -1 it will become the last child.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_group_position (GtkToolPalette *palette,
- GtkWidget *group,
- gint position)
-{
- GtkToolItemGroupInfo group_info;
- gint old_position;
- gpointer src, dst;
- gsize len;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- gtk_tool_palette_repack (palette);
-
- g_return_if_fail (position >= -1);
-
- if (-1 == position)
- position = palette->priv->groups_length - 1;
-
- g_return_if_fail ((guint) position < palette->priv->groups_length);
-
- if (GTK_TOOL_ITEM_GROUP (group) == palette->priv->groups[position].widget)
- return;
-
- old_position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (old_position >= 0);
-
- group_info = palette->priv->groups[old_position];
-
- if (position < old_position)
- {
- dst = palette->priv->groups + position + 1;
- src = palette->priv->groups + position;
- len = old_position - position;
- }
- else
- {
- dst = palette->priv->groups + old_position;
- src = palette->priv->groups + old_position + 1;
- len = position - old_position;
- }
-
- memmove (dst, src, len * sizeof (*palette->priv->groups));
- palette->priv->groups[position] = group_info;
-
- gtk_widget_queue_resize (GTK_WIDGET (palette));
-}
-
-static void
-gtk_tool_palette_group_notify_collapsed (GtkToolItemGroup *group,
- GParamSpec *pspec G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (data);
- guint i;
-
- if (gtk_tool_item_group_get_collapsed (group))
- return;
-
- for (i = 0; i < palette->priv->groups_size; ++i)
- {
- GtkToolItemGroup *current_group = palette->priv->groups[i].widget;
-
- if (current_group && current_group != group)
- gtk_tool_item_group_set_collapsed (palette->priv->groups[i].widget, TRUE);
- }
-}
-
-/**
- * gtk_tool_palette_set_exclusive:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @exclusive: whether the group should be exclusive or not.
- *
- * Sets whether the group should be exclusive or not. If an exclusive group is expanded
- * all other groups are collapsed.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_exclusive (GtkToolPalette *palette,
- GtkWidget *group,
- gboolean exclusive)
-{
- GtkToolItemGroupInfo *group_info;
- gint position;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (position >= 0);
-
- group_info = &palette->priv->groups[position];
-
- if (exclusive == group_info->exclusive)
- return;
-
- group_info->exclusive = exclusive;
-
- if (group_info->exclusive != (0 != group_info->notify_collapsed))
- {
- if (group_info->exclusive)
- {
- group_info->notify_collapsed =
- g_signal_connect (group, "notify::collapsed",
- G_CALLBACK (gtk_tool_palette_group_notify_collapsed),
- palette);
- }
- else
- {
- g_signal_handler_disconnect (group, group_info->notify_collapsed);
- group_info->notify_collapsed = 0;
- }
- }
-
- gtk_tool_palette_group_notify_collapsed (group_info->widget, NULL, palette);
- gtk_widget_child_notify (group, "exclusive");
-}
-
-/**
- * gtk_tool_palette_set_expand:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- * @expand: whether the group should be given extra space.
- *
- * Sets whether the group should be given extra space.
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_set_expand (GtkToolPalette *palette,
- GtkWidget *group,
- gboolean expand)
-{
- GtkToolItemGroupInfo *group_info;
- gint position;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_TOOL_ITEM_GROUP (group));
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_if_fail (position >= 0);
-
- group_info = &palette->priv->groups[position];
-
- if (expand != group_info->expand)
- {
- group_info->expand = expand;
- gtk_widget_queue_resize (GTK_WIDGET (palette));
- gtk_widget_child_notify (group, "expand");
- }
-}
-
-/**
- * gtk_tool_palette_get_group_position:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup.
- *
- * Gets the position of @group in @palette as index. see gtk_tool_palette_set_group_position().
- *
- * Returns: the index of group or -1 if @group is not a child of @palette.
- *
- * Since: 2.18
- */
-gint
-gtk_tool_palette_get_group_position (GtkToolPalette *palette,
- GtkWidget *group)
-{
- guint i;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), -1);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), -1);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- if ((gpointer) group == palette->priv->groups[i].widget)
- return i;
-
- return -1;
-}
-
-/**
- * gtk_tool_palette_get_exclusive:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- *
- * Gets whether group is exclusive or not. See gtk_tool_palette_set_exclusive().
- *
- * Returns: %TRUE if group is exclusive.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_palette_get_exclusive (GtkToolPalette *palette,
- GtkWidget *group)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXCLUSIVE);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXCLUSIVE);
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXCLUSIVE);
-
- return palette->priv->groups[position].exclusive;
-}
-
-/**
- * gtk_tool_palette_get_expand:
- * @palette: an #GtkToolPalette.
- * @group: an #GtkToolItemGroup which is a child of palette.
- *
- * Gets whether group should be given extra space. See gtk_tool_palette_set_expand().
- *
- * Returns: %TRUE if group should be given extra space, %FALSE otherwise.
- *
- * Since: 2.18
- */
-gboolean
-gtk_tool_palette_get_expand (GtkToolPalette *palette,
- GtkWidget *group)
-{
- gint position;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), DEFAULT_CHILD_EXPAND);
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (group), DEFAULT_CHILD_EXPAND);
-
- position = gtk_tool_palette_get_group_position (palette, group);
- g_return_val_if_fail (position >= 0, DEFAULT_CHILD_EXPAND);
-
- return palette->priv->groups[position].expand;
-}
-
-/**
- * gtk_tool_palette_get_drop_item:
- * @palette: an #GtkToolPalette.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the item at position (x, y). See gtk_tool_palette_get_drop_group().
- *
- * Returns: the #GtkToolItem at position or %NULL if there is no such item.
- *
- * Since: 2.18
- */
-GtkToolItem*
-gtk_tool_palette_get_drop_item (GtkToolPalette *palette,
- gint x,
- gint y)
-{
- GtkWidget *group = gtk_tool_palette_get_drop_group (palette, x, y);
-
- if (group)
- return gtk_tool_item_group_get_drop_item (GTK_TOOL_ITEM_GROUP (group),
- x - group->allocation.x,
- y - group->allocation.y);
-
- return NULL;
-}
-
-/**
- * gtk_tool_palette_get_drop_group:
- * @palette: an #GtkToolPalette.
- * @x: the x position.
- * @y: the y position.
- *
- * Gets the group at position (x, y).
- *
- * Returns: the #GtkToolItemGroup at position or %NULL if there is no such group.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_get_drop_group (GtkToolPalette *palette,
- gint x,
- gint y)
-{
- GtkAllocation *allocation;
- guint i;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
-
- allocation = >K_WIDGET (palette)->allocation;
-
- g_return_val_if_fail (x >= 0 && x < allocation->width, NULL);
- g_return_val_if_fail (y >= 0 && y < allocation->height, NULL);
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
- GtkWidget *widget;
- gint x0, y0;
-
- if (!group->widget)
- continue;
-
- widget = GTK_WIDGET (group->widget);
-
- x0 = x - widget->allocation.x;
- y0 = y - widget->allocation.y;
-
- if (x0 >= 0 && x0 < widget->allocation.width &&
- y0 >= 0 && y0 < widget->allocation.height)
- return widget;
- }
-
- return NULL;
-}
-
-/**
- * gtk_tool_palette_get_drag_item:
- * @palette: an #GtkToolPalette.
- * @selection: a #GtkSelectionData.
- *
- * Get the dragged item from the selection. This could be a #GtkToolItem or
- * an #GtkToolItemGroup.
- *
- * Returns: the dragged item in selection.
- *
- * Since: 2.18
- */
-GtkWidget*
-gtk_tool_palette_get_drag_item (GtkToolPalette *palette,
- const GtkSelectionData *selection)
-{
- GtkToolPaletteDragData *data;
-
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- g_return_val_if_fail (NULL != selection, NULL);
-
- g_return_val_if_fail (selection->format == 8, NULL);
- g_return_val_if_fail (selection->length == sizeof (GtkToolPaletteDragData), NULL);
- g_return_val_if_fail (selection->target == dnd_target_atom_item ||
- selection->target == dnd_target_atom_group,
- NULL);
-
- data = (GtkToolPaletteDragData*) selection->data;
-
- g_return_val_if_fail (data->palette == palette, NULL);
-
- if (dnd_target_atom_item == selection->target)
- g_return_val_if_fail (GTK_IS_TOOL_ITEM (data->item), NULL);
- else if (dnd_target_atom_group == selection->target)
- g_return_val_if_fail (GTK_IS_TOOL_ITEM_GROUP (data->item), NULL);
-
- return data->item;
-}
-
-/**
- * gtk_tool_palette_set_drag_source:
- * @palette: an #GtkToolPalette.
- * @targets: the #GtkToolPaletteDragTargets which the widget should support.
- *
- * Sets the tool palette as a drag source. Enables all groups and items in
- * the tool palette as drag sources on button 1 and button 3 press with copy
- * and move actions.
- *
- * See gtk_drag_source_set().
- *
- * Since: 2.18
- *
- */
-void
-gtk_tool_palette_set_drag_source (GtkToolPalette *palette,
- GtkToolPaletteDragTargets targets)
-{
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
-
- if ((palette->priv->drag_source & targets) == targets)
- return;
-
- palette->priv->drag_source |= targets;
-
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- if (palette->priv->groups[i].widget)
- gtk_container_forall (GTK_CONTAINER (palette->priv->groups[i].widget),
- _gtk_tool_palette_child_set_drag_source,
- palette);
- }
-}
-
-/**
- * gtk_tool_palette_add_drag_dest:
- * @palette: an #GtkToolPalette.
- * @widget: a #GtkWidget which should be a drag destination for palette.
- * @flags: the flags that specify what actions GTK+ should take for drops on that widget.
- * @targets: the #GtkToolPaletteDragTargets which the widget should support.
- * @actions: the #GdkDragAction<!-- -->s which the widget should suppport.
- *
- * Sets the tool palette as drag source (see gtk_tool_palette_set_drag_source) and
- * sets widget as a drag destination for drags from palette. With flags the actions
- * (like highlighting and target checking) which should be performed by GTK+ for
- * drops on widget can be specified. With targets the supported drag targets
- * (groups and/or items) can be specified. With actions the supported drag actions
- * (copy and move) can be specified.
- *
- * See gtk_drag_dest_set().
- *
- * Since: 2.18
- */
-void
-gtk_tool_palette_add_drag_dest (GtkToolPalette *palette,
- GtkWidget *widget,
- GtkDestDefaults flags,
- GtkToolPaletteDragTargets targets,
- GdkDragAction actions)
-{
- GtkTargetEntry entries[G_N_ELEMENTS (dnd_targets)];
- gint n_entries = 0;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- gtk_tool_palette_set_drag_source (palette,
- targets);
-
- if (targets & GTK_TOOL_PALETTE_DRAG_ITEMS)
- entries[n_entries++] = dnd_targets[0];
- if (targets & GTK_TOOL_PALETTE_DRAG_GROUPS)
- entries[n_entries++] = dnd_targets[1];
-
- gtk_drag_dest_set (widget, flags, entries, n_entries, actions);
-}
-
-void
-_gtk_tool_palette_get_item_size (GtkToolPalette *palette,
- GtkRequisition *item_size,
- gboolean homogeneous_only,
- gint *requested_rows)
-{
- GtkRequisition max_requisition;
- gint max_rows;
- guint i;
-
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- g_return_if_fail (NULL != item_size);
-
- max_requisition.width = 0;
- max_requisition.height = 0;
- max_rows = 0;
-
- /* iterate over all groups and calculate the max item_size and max row request */
- for (i = 0; i < palette->priv->groups_length; ++i)
- {
- GtkRequisition requisition;
- gint rows;
- GtkToolItemGroupInfo *group = &palette->priv->groups[i];
-
- if (!group->widget)
- continue;
-
- _gtk_tool_item_group_item_size_request (group->widget, &requisition, homogeneous_only, &rows);
-
- max_requisition.width = MAX (max_requisition.width, requisition.width);
- max_requisition.height = MAX (max_requisition.height, requisition.height);
- max_rows = MAX (max_rows, rows);
- }
-
- *item_size = max_requisition;
- if (requested_rows)
- *requested_rows = max_rows;
-}
-
-static void
-gtk_tool_palette_item_drag_data_get (GtkWidget *widget,
- GdkDragContext *context G_GNUC_UNUSED,
- GtkSelectionData *selection,
- guint info G_GNUC_UNUSED,
- guint time G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL };
-
- if (selection->target == dnd_target_atom_item)
- drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM);
-
- if (drag_data.item)
- gtk_selection_data_set (selection, selection->target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
-}
-
-static void
-gtk_tool_palette_child_drag_data_get (GtkWidget *widget,
- GdkDragContext *context G_GNUC_UNUSED,
- GtkSelectionData *selection,
- guint info G_GNUC_UNUSED,
- guint time G_GNUC_UNUSED,
- gpointer data)
-{
- GtkToolPaletteDragData drag_data = { GTK_TOOL_PALETTE (data), NULL };
-
- if (selection->target == dnd_target_atom_group)
- drag_data.item = gtk_widget_get_ancestor (widget, GTK_TYPE_TOOL_ITEM_GROUP);
-
- if (drag_data.item)
- gtk_selection_data_set (selection, selection->target, 8,
- (guchar*) &drag_data, sizeof (drag_data));
-}
-
-void
-_gtk_tool_palette_child_set_drag_source (GtkWidget *child,
- gpointer data)
-{
- GtkToolPalette *palette = GTK_TOOL_PALETTE (data);
-
- /* Check drag_source,
- * to work properly when called from gtk_tool_item_group_insert().
- */
- if (!palette->priv->drag_source)
- return;
-
- if (GTK_IS_TOOL_ITEM (child) &&
- (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_ITEMS))
- {
- /* Connect to child instead of the item itself,
- * to work arround bug 510377.
- */
- if (GTK_IS_TOOL_BUTTON (child))
- child = gtk_bin_get_child (GTK_BIN (child));
-
- if (!child)
- return;
-
- gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
- &dnd_targets[0], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
- g_signal_connect (child, "drag-data-get",
- G_CALLBACK (gtk_tool_palette_item_drag_data_get),
- palette);
- }
- else if (GTK_IS_BUTTON (child) &&
- (palette->priv->drag_source & GTK_TOOL_PALETTE_DRAG_GROUPS))
- {
- gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
- &dnd_targets[1], 1, GDK_ACTION_COPY | GDK_ACTION_MOVE);
-
- g_signal_connect (child, "drag-data-get",
- G_CALLBACK (gtk_tool_palette_child_drag_data_get),
- palette);
- }
-}
-
-/**
- * gtk_tool_palette_get_drag_target_item:
- *
- * Get the target entry for a dragged #GtkToolItem.
- *
- * Returns: the #GtkTargetEntry for a dragged item.
- *
- * Since: 2.18
- */
-G_CONST_RETURN GtkTargetEntry*
-gtk_tool_palette_get_drag_target_item (void)
-{
- return &dnd_targets[0];
-}
-
-/**
- * gtk_tool_palette_get_drag_target_group:
- *
- * Get the target entry for a dragged #GtkToolItemGroup.
- *
- * Returns: the #GtkTargetEntry for a dragged group.
- *
- * Since: 2.18
- */
-G_CONST_RETURN GtkTargetEntry*
-gtk_tool_palette_get_drag_target_group (void)
-{
- return &dnd_targets[1];
-}
-
-void
-_gtk_tool_palette_set_expanding_child (GtkToolPalette *palette,
- GtkWidget *widget)
-{
- g_return_if_fail (GTK_IS_TOOL_PALETTE (palette));
- palette->priv->expanding_child = widget;
-}
-
-GtkAdjustment*
-gtk_tool_palette_get_hadjustment (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- return palette->priv->hadjustment;
-}
-
-GtkAdjustment*
-gtk_tool_palette_get_vadjustment (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
- return palette->priv->vadjustment;
-}
-
-#ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
-
-GtkSizeGroup *
-_gtk_tool_palette_get_size_group (GtkToolPalette *palette)
-{
- g_return_val_if_fail (GTK_IS_TOOL_PALETTE (palette), NULL);
-
- return palette->priv->text_size_group;
-}
-
-#endif